1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * IKEv2 responder (RFC 4306) for EAP-IKEV2 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2007, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "dh_groups.h" 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "ikev2.h" 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ikev2_responder_deinit(struct ikev2_responder_data *data) 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_free_keys(&data->keys); 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->i_dh_public); 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->r_dh_private); 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->IDi); 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->IDr); 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->shared_secret); 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->i_sign_msg); 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->r_sign_msg); 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->key_pad); 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_derive_keys(struct ikev2_responder_data *data) 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *buf, *pos, *pad, skeyseed[IKEV2_MAX_HASH_LEN]; 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t buf_len, pad_len; 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *shared; 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_integ_alg *integ; 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_prf_alg *prf; 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_encr_alg *encr; 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *addr[2]; 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len[2]; 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* RFC 4306, Sect. 2.14 */ 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt integ = ikev2_get_integ(data->proposal.integ); 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prf = ikev2_get_prf(data->proposal.prf); 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt encr = ikev2_get_encr(data->proposal.encr); 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (integ == NULL || prf == NULL || encr == NULL) { 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported proposal"); 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt shared = dh_derive_shared(data->i_dh_public, data->r_dh_private, 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->dh); 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (shared == NULL) 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Construct Ni | Nr | SPIi | SPIr */ 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf_len = data->i_nonce_len + data->r_nonce_len + 2 * IKEV2_SPI_LEN; 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_malloc(buf_len); 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) { 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(shared); 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = buf; 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, data->i_nonce, data->i_nonce_len); 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += data->i_nonce_len; 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, data->r_nonce, data->r_nonce_len); 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += data->r_nonce_len; 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, data->i_spi, IKEV2_SPI_LEN); 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += IKEV2_SPI_LEN; 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, data->r_spi, IKEV2_SPI_LEN); 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#if __BYTE_ORDER == __LITTLE_ENDIAN 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int i; 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *tmp = pos - IKEV2_SPI_LEN; 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Incorrect byte re-ordering on little endian hosts.. */ 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < IKEV2_SPI_LEN; i++) 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *tmp++ = data->i_spi[IKEV2_SPI_LEN - 1 - i]; 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < IKEV2_SPI_LEN; i++) 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *tmp++ = data->r_spi[IKEV2_SPI_LEN - 1 - i]; 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* SKEYSEED = prf(Ni | Nr, g^ir) */ 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Use zero-padding per RFC 4306, Sect. 2.14 */ 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pad_len = data->dh->prime_len - wpabuf_len(shared); 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Shared secret is not zero-padded correctly */ 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pad_len = 0; 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pad = os_zalloc(pad_len ? pad_len : 1); 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pad == NULL) { 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(shared); 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[0] = pad; 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[0] = pad_len; 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[1] = wpabuf_head(shared); 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[1] = wpabuf_len(shared); 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_prf_hash(prf->id, buf, data->i_nonce_len + data->r_nonce_len, 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 2, addr, len, skeyseed) < 0) { 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(shared); 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(pad); 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(pad); 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(shared); 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* DH parameters are not needed anymore, so free them */ 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->i_dh_public); 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->i_dh_public = NULL; 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->r_dh_private); 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->r_dh_private = NULL; 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SKEYSEED", 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt skeyseed, prf->hash_len); 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = ikev2_derive_sk_keys(prf, integ, encr, skeyseed, buf, buf_len, 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &data->keys); 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_parse_transform(struct ikev2_proposal_data *prop, 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos, const u8 *end) 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int transform_len; 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_transform *t; 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 transform_id; 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *tend; 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (end - pos < (int) sizeof(*t)) { 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short transform"); 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t = (const struct ikev2_transform *) pos; 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt transform_len = WPA_GET_BE16(t->transform_length); 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (transform_len < (int) sizeof(*t) || pos + transform_len > end) { 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d", 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt transform_len); 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tend = pos + transform_len; 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt transform_id = WPA_GET_BE16(t->transform_id); 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Transform:"); 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Transform Length: %d " 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Transform Type: %d Transform ID: %d", 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t->type, transform_len, t->transform_type, transform_id); 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (t->type != 0 && t->type != 3) { 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Transform type"); 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = (const u8 *) (t + 1); 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos < tend) { 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: Transform Attributes", 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos, tend - pos); 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (t->transform_type) { 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_TRANSFORM_ENCR: 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_get_encr(transform_id)) { 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (transform_id == ENCR_AES_CBC) { 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (tend - pos != 4) { 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: No " 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Transform Attr for AES"); 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (WPA_GET_BE16(pos) != 0x001d /* ?? */) { 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Not a " 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Key Size attribute for " 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "AES"); 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* CCNS_PL */ 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (WPA_GET_BE16(pos) != 0x800e) { 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Not a " 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Key Size attribute for " 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "AES"); 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (WPA_GET_BE16(pos + 2) != 128) { 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: " 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Unsupported AES key size " 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%d bits", 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_GET_BE16(pos + 2)); 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prop->encr = transform_id; 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_TRANSFORM_PRF: 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_get_prf(transform_id)) 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prop->prf = transform_id; 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_TRANSFORM_INTEG: 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_get_integ(transform_id)) 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prop->integ = transform_id; 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_TRANSFORM_DH: 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (dh_groups_get(transform_id)) 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prop->dh = transform_id; 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return transform_len; 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_parse_proposal(struct ikev2_proposal_data *prop, 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos, const u8 *end) 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pend, *ppos; 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int proposal_len, i; 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_proposal *p; 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (end - pos < (int) sizeof(*p)) { 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short proposal"); 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* FIX: AND processing if multiple proposals use the same # */ 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt p = (const struct ikev2_proposal *) pos; 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt proposal_len = WPA_GET_BE16(p->proposal_length); 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (proposal_len < (int) sizeof(*p) || pos + proposal_len > end) { 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid proposal length %d", 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt proposal_len); 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: SAi1 Proposal # %d", 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt p->proposal_num); 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Proposal Length: %d " 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " Protocol ID: %d", 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt p->type, proposal_len, p->protocol_id); 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: SPI Size: %d Transforms: %d", 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt p->spi_size, p->num_transforms); 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (p->type != 0 && p->type != 2) { 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal type"); 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (p->protocol_id != IKEV2_PROTOCOL_IKE) { 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Unexpected Protocol ID " 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(only IKE allowed for EAP-IKEv2)"); 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (p->proposal_num != prop->proposal_num) { 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (p->proposal_num == prop->proposal_num + 1) 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prop->proposal_num = p->proposal_num; 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else { 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal #"); 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ppos = (const u8 *) (p + 1); 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pend = pos + proposal_len; 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ppos + p->spi_size > pend) { 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI " 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "in proposal"); 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (p->spi_size) { 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: SPI", 289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ppos, p->spi_size); 290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ppos += p->spi_size; 291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * For initial IKE_SA negotiation, SPI Size MUST be zero; for 295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * subsequent negotiations, it must be 8 for IKE. We only support 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * initial case for now. 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (p->spi_size != 0) { 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected SPI Size"); 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (p->num_transforms == 0) { 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: At least one transform required"); 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < (int) p->num_transforms; i++) { 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int tlen = ikev2_parse_transform(prop, ppos, pend); 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (tlen < 0) 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ppos += tlen; 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ppos != pend) { 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected data after " 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "transforms"); 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return proposal_len; 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_process_sai1(struct ikev2_responder_data *data, 326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *sai1, size_t sai1_len) 327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_proposal_data prop; 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos, *end; 330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int found = 0; 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Security Association Payloads: <Proposals> */ 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sai1 == NULL) { 335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: SAi1 not received"); 336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&prop, 0, sizeof(prop)); 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prop.proposal_num = 1; 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = sai1; 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt end = sai1 + sai1_len; 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (pos < end) { 346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int plen; 347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prop.integ = -1; 349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prop.prf = -1; 350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prop.encr = -1; 351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prop.dh = -1; 352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = ikev2_parse_proposal(&prop, pos, end); 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (plen < 0) 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!found && prop.integ != -1 && prop.prf != -1 && 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prop.encr != -1 && prop.dh != -1) { 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(&data->proposal, &prop, sizeof(prop)); 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->dh = dh_groups_get(prop.dh); 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt found = 1; 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += plen; 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos != end) { 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected data after proposals"); 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!found) { 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No acceptable proposal found"); 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Accepted proposal #%d: ENCR:%d PRF:%d " 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "INTEG:%d D-H:%d", data->proposal.proposal_num, 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->proposal.encr, data->proposal.prf, 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->proposal.integ, data->proposal.dh); 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_process_kei(struct ikev2_responder_data *data, 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *kei, size_t kei_len) 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 group; 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Key Exchange Payload: 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * DH Group # (16 bits) 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * RESERVED (16 bits) 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Key Exchange Data (Diffie-Hellman public value) 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kei == NULL) { 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: KEi not received"); 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kei_len < 4 + 96) { 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too show Key Exchange Payload"); 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt group = WPA_GET_BE16(kei); 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u", group); 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (group != data->proposal.dh) { 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u does not match " 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "with the selected proposal (%u)", 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt group, data->proposal.dh); 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Reject message with Notify payload of type 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * INVALID_KE_PAYLOAD (RFC 4306, Sect. 3.4) */ 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->error_type = INVALID_KE_PAYLOAD; 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = NOTIFY; 418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->dh == NULL) { 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported DH group"); 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* RFC 4306, Section 3.4: 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * The length of DH public value MUST be equal to the lenght of the 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * prime modulus. 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kei_len - 4 != data->dh->prime_len) { 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid DH public value length " 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%ld (expected %ld)", 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (long) (kei_len - 4), (long) data->dh->prime_len); 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->i_dh_public); 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->i_dh_public = wpabuf_alloc(kei_len - 4); 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->i_dh_public == NULL) 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_data(data->i_dh_public, kei + 4, kei_len - 4); 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEi Diffie-Hellman Public Value", 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->i_dh_public); 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_process_ni(struct ikev2_responder_data *data, 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *ni, size_t ni_len) 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ni == NULL) { 454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Ni not received"); 455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ni_len < IKEV2_NONCE_MIN_LEN || ni_len > IKEV2_NONCE_MAX_LEN) { 459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid Ni length %ld", 460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (long) ni_len); 461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Zeros are removed incorrectly from the beginning of the nonces */ 466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (ni_len > 1 && *ni == 0) { 467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ni_len--; 468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ni++; 469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->i_nonce_len = ni_len; 473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->i_nonce, ni, ni_len); 474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "IKEV2: Ni", 475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->i_nonce, data->i_nonce_len); 476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_process_sa_init(struct ikev2_responder_data *data, 482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_hdr *hdr, 483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_payloads *pl) 484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_process_sai1(data, pl->sa, pl->sa_len) < 0 || 486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_process_kei(data, pl->ke, pl->ke_len) < 0 || 487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_process_ni(data, pl->nonce, pl->nonce_len) < 0) 488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN); 491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_process_idi(struct ikev2_responder_data *data, 497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *idi, size_t idi_len) 498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 id_type; 500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (idi == NULL) { 502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No IDi received"); 503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (idi_len < 4) { 507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short IDi payload"); 508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt id_type = idi[0]; 512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt idi += 4; 513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt idi_len -= 4; 514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: IDi ID Type %d", id_type); 516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "IKEV2: IDi", idi, idi_len); 517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->IDi); 518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->IDi = os_malloc(idi_len); 519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->IDi == NULL) 520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->IDi, idi, idi_len); 522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->IDi_len = idi_len; 523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->IDi_type = id_type; 524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_process_cert(struct ikev2_responder_data *data, 530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *cert, size_t cert_len) 531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 cert_encoding; 533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (cert == NULL) { 535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->peer_auth == PEER_AUTH_CERT) { 536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No Certificate received"); 537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (cert_len < 1) { 543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No Cert Encoding field"); 544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cert_encoding = cert[0]; 548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cert++; 549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cert_len--; 550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Cert Encoding %d", cert_encoding); 552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "IKEV2: Certificate Data", cert, cert_len); 553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: validate certificate */ 555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_process_auth_cert(struct ikev2_responder_data *data, 561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 method, const u8 *auth, size_t auth_len) 562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (method != AUTH_RSA_SIGN) { 564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " 565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "method %d", method); 566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: validate AUTH */ 570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_process_auth_secret(struct ikev2_responder_data *data, 575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 method, const u8 *auth, 576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t auth_len) 577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 auth_data[IKEV2_MAX_HASH_LEN]; 579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_prf_alg *prf; 580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (method != AUTH_SHARED_KEY_MIC) { 582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " 583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "method %d", method); 584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* msg | Nr | prf(SK_pi,IDi') */ 588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_derive_auth_data(data->proposal.prf, data->i_sign_msg, 589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->IDi, data->IDi_len, data->IDi_type, 590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &data->keys, 1, data->shared_secret, 591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->shared_secret_len, 592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->r_nonce, data->r_nonce_len, 593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->key_pad, data->key_pad_len, 594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt auth_data) < 0) { 595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data"); 596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->i_sign_msg); 600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->i_sign_msg = NULL; 601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prf = ikev2_get_prf(data->proposal.prf); 603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (prf == NULL) 604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (auth_len != prf->hash_len || 607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(auth, auth_data, auth_len) != 0) { 608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data"); 609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data", 610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt auth, auth_len); 611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: Expected Authentication Data", 612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt auth_data, prf->hash_len); 613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->error_type = AUTHENTICATION_FAILED; 614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = NOTIFY; 615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Server authenticated successfully " 619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "using shared keys"); 620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_process_auth(struct ikev2_responder_data *data, 626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *auth, size_t auth_len) 627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 auth_method; 629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (auth == NULL) { 631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No Authentication Payload"); 632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (auth_len < 4) { 636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short Authentication " 637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Payload"); 638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt auth_method = auth[0]; 642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt auth += 4; 643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt auth_len -= 4; 644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Auth Method %d", auth_method); 646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "IKEV2: Authentication Data", auth, auth_len); 647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (data->peer_auth) { 649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PEER_AUTH_CERT: 650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ikev2_process_auth_cert(data, auth_method, auth, 651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt auth_len); 652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PEER_AUTH_SECRET: 653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ikev2_process_auth_secret(data, auth_method, auth, 654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt auth_len); 655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_process_sa_auth_decrypted(struct ikev2_responder_data *data, 662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 next_payload, 663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *payload, size_t payload_len) 664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_payloads pl; 666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads"); 668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_parse_payloads(&pl, next_payload, payload, payload + 670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payload_len) < 0) { 671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted " 672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "payloads"); 673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_process_idi(data, pl.idi, pl.idi_len) < 0 || 677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_process_cert(data, pl.cert, pl.cert_len) < 0 || 678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_process_auth(data, pl.auth, pl.auth_len) < 0) 679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_process_sa_auth(struct ikev2_responder_data *data, 686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_hdr *hdr, 687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_payloads *pl) 688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *decrypted; 690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t decrypted_len; 691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt decrypted = ikev2_decrypt_payload(data->proposal.encr, 694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->proposal.integ, 695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &data->keys, 1, hdr, pl->encrypted, 696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pl->encrypted_len, &decrypted_len); 697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (decrypted == NULL) 698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = ikev2_process_sa_auth_decrypted(data, pl->encr_next_payload, 701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt decrypted, decrypted_len); 702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(decrypted); 703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_validate_rx_state(struct ikev2_responder_data *data, 709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 exchange_type, u32 message_id) 710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (data->state) { 712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case SA_INIT: 713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Expect to receive IKE_SA_INIT: HDR, SAi1, KEi, Ni */ 714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (exchange_type != IKE_SA_INIT) { 715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " 716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%u in SA_INIT state", exchange_type); 717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (message_id != 0) { 720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " 721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "in SA_INIT state", message_id); 722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case SA_AUTH: 726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Expect to receive IKE_SA_AUTH: 727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * HDR, SK {IDi, [CERT,] [CERTREQ,] [IDr,] 728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * AUTH, SAi2, TSi, TSr} 729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (exchange_type != IKE_SA_AUTH) { 731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " 732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%u in SA_AUTH state", exchange_type); 733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (message_id != 1) { 736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " 737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "in SA_AUTH state", message_id); 738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CHILD_SA: 742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (exchange_type != CREATE_CHILD_SA) { 743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " 744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%u in CHILD_SA state", exchange_type); 745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (message_id != 2) { 748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " 749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "in CHILD_SA state", message_id); 750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case NOTIFY: 754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_DONE: 755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_FAILED: 756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint ikev2_responder_process(struct ikev2_responder_data *data, 764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpabuf *buf) 765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_hdr *hdr; 767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 length, message_id; 768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos, *end; 769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_payloads pl; 770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_MSGDUMP, "IKEV2: Received message (len %lu)", 772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) wpabuf_len(buf)); 773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpabuf_len(buf) < sizeof(*hdr)) { 775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short frame to include HDR"); 776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->error_type = 0; 780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr = (const struct ikev2_hdr *) wpabuf_head(buf); 781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt end = wpabuf_head_u8(buf) + wpabuf_len(buf); 782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt message_id = WPA_GET_BE32(hdr->message_id); 783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt length = WPA_GET_BE32(hdr->length); 784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI", 786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->i_spi, IKEV2_SPI_LEN); 787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI", 788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->r_spi, IKEV2_SPI_LEN); 789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Version: 0x%x " 790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Exchange Type: %u", 791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->next_payload, hdr->version, hdr->exchange_type); 792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Message ID: %u Length: %u", 793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt message_id, length); 794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (hdr->version != IKEV2_VERSION) { 796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported HDR version 0x%x " 797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(expected 0x%x)", hdr->version, IKEV2_VERSION); 798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (length != wpabuf_len(buf)) { 802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid length (HDR: %lu != " 803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "RX: %lu)", (unsigned long) length, 804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) wpabuf_len(buf)); 805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_validate_rx_state(data, hdr->exchange_type, message_id) < 0) 809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 811526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((hdr->flags & (IKEV2_HDR_INITIATOR | IKEV2_HDR_RESPONSE)) != 812526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IKEV2_HDR_INITIATOR) { 813526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Flags value 0x%x", 814526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->flags); 815526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 816526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 817526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 818526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state != SA_INIT) { 819526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN) != 0) { 820526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA " 821526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Initiator's SPI"); 822526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 823526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 824526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN) != 0) { 825526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA " 826526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Responder's SPI"); 827526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 828526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 829526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 830526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 831526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = (const u8 *) (hdr + 1); 832526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_parse_payloads(&pl, hdr->next_payload, pos, end) < 0) 833526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 834526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 835526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state == SA_INIT) { 836526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->last_msg = LAST_MSG_SA_INIT; 837526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_process_sa_init(data, hdr, &pl) < 0) { 838526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state == NOTIFY) 839526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 840526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 841526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 842526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->i_sign_msg); 843526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->i_sign_msg = wpabuf_dup(buf); 844526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 845526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 846526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state == SA_AUTH) { 847526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->last_msg = LAST_MSG_SA_AUTH; 848526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_process_sa_auth(data, hdr, &pl) < 0) { 849526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state == NOTIFY) 850526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 851526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 852526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 853526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 854526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 855526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 856526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 857526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 858526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 859526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void ikev2_build_hdr(struct ikev2_responder_data *data, 860526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *msg, u8 exchange_type, 861526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 next_payload, u32 message_id) 862526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 863526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_hdr *hdr; 864526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 865526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding HDR"); 866526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 867526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* HDR - RFC 4306, Sect. 3.1 */ 868526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr = wpabuf_put(msg, sizeof(*hdr)); 869526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(hdr->i_spi, data->i_spi, IKEV2_SPI_LEN); 870526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(hdr->r_spi, data->r_spi, IKEV2_SPI_LEN); 871526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->next_payload = next_payload; 872526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->version = IKEV2_VERSION; 873526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->exchange_type = exchange_type; 874526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->flags = IKEV2_HDR_RESPONSE; 875526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE32(hdr->message_id, message_id); 876526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 877526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 878526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 879526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_build_sar1(struct ikev2_responder_data *data, 880526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *msg, u8 next_payload) 881526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 882526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_payload_hdr *phdr; 883526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t plen; 884526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_proposal *p; 885526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_transform *t; 886526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 887526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding SAr1 payload"); 888526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 889526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* SAr1 - RFC 4306, Sect. 2.7 and 3.3 */ 890526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 891526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->next_payload = next_payload; 892526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->flags = 0; 893526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 894526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt p = wpabuf_put(msg, sizeof(*p)); 895526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 896526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Seems to require that the Proposal # is 1 even though RFC 4306 897526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Sect 3.3.1 has following requirement "When a proposal is accepted, 898526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * all of the proposal numbers in the SA payload MUST be the same and 899526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * MUST match the number on the proposal sent that was accepted.". 900526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 901526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt p->proposal_num = 1; 902526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* CCNS_PL */ 903526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt p->proposal_num = data->proposal.proposal_num; 904526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 905526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt p->protocol_id = IKEV2_PROTOCOL_IKE; 906526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt p->num_transforms = 4; 907526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 908526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t = wpabuf_put(msg, sizeof(*t)); 909526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t->type = 3; 910526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t->transform_type = IKEV2_TRANSFORM_ENCR; 911526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(t->transform_id, data->proposal.encr); 912526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->proposal.encr == ENCR_AES_CBC) { 913526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Transform Attribute: Key Len = 128 bits */ 914526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 915526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_be16(msg, 0x001d); /* ?? */ 916526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* CCNS_PL */ 917526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */ 918526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 919526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_be16(msg, 128); /* 128-bit key */ 920526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 921526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t; 922526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(t->transform_length, plen); 923526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 924526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t = wpabuf_put(msg, sizeof(*t)); 925526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t->type = 3; 926526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(t->transform_length, sizeof(*t)); 927526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t->transform_type = IKEV2_TRANSFORM_PRF; 928526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(t->transform_id, data->proposal.prf); 929526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 930526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t = wpabuf_put(msg, sizeof(*t)); 931526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t->type = 3; 932526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(t->transform_length, sizeof(*t)); 933526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t->transform_type = IKEV2_TRANSFORM_INTEG; 934526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(t->transform_id, data->proposal.integ); 935526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 936526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t = wpabuf_put(msg, sizeof(*t)); 937526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(t->transform_length, sizeof(*t)); 938526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt t->transform_type = IKEV2_TRANSFORM_DH; 939526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(t->transform_id, data->proposal.dh); 940526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 941526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) p; 942526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(p->proposal_length, plen); 943526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 944526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 945526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 946526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 947526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 948526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 949526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 950526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 951526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_build_ker(struct ikev2_responder_data *data, 952526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *msg, u8 next_payload) 953526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 954526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_payload_hdr *phdr; 955526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t plen; 956526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *pv; 957526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 958526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding KEr payload"); 959526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 960526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pv = dh_init(data->dh, &data->r_dh_private); 961526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pv == NULL) { 962526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Failed to initialize DH"); 963526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 964526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 965526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 966526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* KEr - RFC 4306, Sect. 3.4 */ 967526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 968526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->next_payload = next_payload; 969526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->flags = 0; 970526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 971526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_be16(msg, data->proposal.dh); /* DH Group # */ 972526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put(msg, 2); /* RESERVED */ 973526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 974526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * RFC 4306, Sect. 3.4: possible zero padding for public value to 975526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * match the length of the prime. 976526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 977526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv)); 978526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_buf(msg, pv); 979526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(pv); 980526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 981526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 982526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 983526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 984526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 985526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 986526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 987526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_build_nr(struct ikev2_responder_data *data, 988526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *msg, u8 next_payload) 989526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 990526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_payload_hdr *phdr; 991526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t plen; 992526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 993526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding Nr payload"); 994526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 995526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Nr - RFC 4306, Sect. 3.9 */ 996526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 997526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->next_payload = next_payload; 998526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->flags = 0; 999526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_data(msg, data->r_nonce, data->r_nonce_len); 1000526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 1001526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 1002526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 1003526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1004526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1005526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1006526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_build_idr(struct ikev2_responder_data *data, 1007526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *msg, u8 next_payload) 1008526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1009526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_payload_hdr *phdr; 1010526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t plen; 1011526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1012526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding IDr payload"); 1013526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1014526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->IDr == NULL) { 1015526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No IDr available"); 1016526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1017526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1018526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1019526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* IDr - RFC 4306, Sect. 3.5 */ 1020526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 1021526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->next_payload = next_payload; 1022526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->flags = 0; 1023526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(msg, ID_KEY_ID); 1024526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put(msg, 3); /* RESERVED */ 1025526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_data(msg, data->IDr, data->IDr_len); 1026526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 1027526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 1028526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 1029526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1030526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1031526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1032526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_build_auth(struct ikev2_responder_data *data, 1033526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *msg, u8 next_payload) 1034526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1035526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_payload_hdr *phdr; 1036526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t plen; 1037526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_prf_alg *prf; 1038526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1039526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding AUTH payload"); 1040526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1041526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prf = ikev2_get_prf(data->proposal.prf); 1042526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (prf == NULL) 1043526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1044526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1045526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Authentication - RFC 4306, Sect. 3.8 */ 1046526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 1047526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->next_payload = next_payload; 1048526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->flags = 0; 1049526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(msg, AUTH_SHARED_KEY_MIC); 1050526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put(msg, 3); /* RESERVED */ 1051526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1052526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* msg | Ni | prf(SK_pr,IDr') */ 1053526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_derive_auth_data(data->proposal.prf, data->r_sign_msg, 1054526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->IDr, data->IDr_len, ID_KEY_ID, 1055526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &data->keys, 0, data->shared_secret, 1056526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->shared_secret_len, 1057526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->i_nonce, data->i_nonce_len, 1058526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->key_pad, data->key_pad_len, 1059526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put(msg, prf->hash_len)) < 0) { 1060526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data"); 1061526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1062526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1063526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->r_sign_msg); 1064526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->r_sign_msg = NULL; 1065526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1066526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 1067526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 1068526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 1069526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1070526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1071526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1072526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ikev2_build_notification(struct ikev2_responder_data *data, 1073526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *msg, u8 next_payload) 1074526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1075526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_payload_hdr *phdr; 1076526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t plen; 1077526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1078526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding Notification payload"); 1079526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1080526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->error_type == 0) { 1081526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No Notify Message Type " 1082526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "available"); 1083526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1084526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1085526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1086526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Notify - RFC 4306, Sect. 3.10 */ 1087526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 1088526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->next_payload = next_payload; 1089526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->flags = 0; 1090526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 1091526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(msg, 1); /* Protocol ID: IKE_SA notification */ 1092526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* CCNS_PL */ 1093526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(msg, 0); /* Protocol ID: no existing SA */ 1094526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 1095526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(msg, 0); /* SPI Size */ 1096526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_be16(msg, data->error_type); 1097526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1098526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (data->error_type) { 1099526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case INVALID_KE_PAYLOAD: 1100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->proposal.dh == -1) { 1101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No DH Group selected for " 1102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "INVALID_KE_PAYLOAD notifications"); 1103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_be16(msg, data->proposal.dh); 1106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: INVALID_KE_PAYLOAD - request " 1107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "DH Group #%d", data->proposal.dh); 1108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case AUTHENTICATION_FAILED: 1110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* no associated data */ 1111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 1113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported Notify Message Type " 1114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%d", data->error_type); 1115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 1119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 1120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 1121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * ikev2_build_sa_init(struct ikev2_responder_data *data) 1125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *msg; 1127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* build IKE_SA_INIT: HDR, SAr1, KEr, Nr, [CERTREQ], [SK{IDr}] */ 1129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_get_random(data->r_spi, IKEV2_SPI_LEN)) 1131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI", 1133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->r_spi, IKEV2_SPI_LEN); 1134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->r_nonce_len = IKEV2_NONCE_MIN_LEN; 1136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_get_random(data->r_nonce, data->r_nonce_len)) 1137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 1139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Zeros are removed incorrectly from the beginning of the nonces in 1140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * key derivation; as a workaround, make sure Nr does not start with 1141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * zero.. */ 1142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->r_nonce[0] == 0) 1143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->r_nonce[0] = 1; 1144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 1145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: Nr", data->r_nonce, data->r_nonce_len); 1146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1500); 1148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg == NULL) 1149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_SA, 0); 1152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_build_sar1(data, msg, IKEV2_PAYLOAD_KEY_EXCHANGE) || 1153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_build_ker(data, msg, IKEV2_PAYLOAD_NONCE) || 1154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_build_nr(data, msg, data->peer_auth == PEER_AUTH_SECRET ? 1155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IKEV2_PAYLOAD_ENCRYPTED : 1156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) { 1157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(msg); 1158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_derive_keys(data)) { 1162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(msg); 1163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->peer_auth == PEER_AUTH_CERT) { 1167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: CERTREQ with SHA-1 hashes of Subject Public Key Info 1168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * for trust agents */ 1169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->peer_auth == PEER_AUTH_SECRET) { 1172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *plain = wpabuf_alloc(data->IDr_len + 1000); 1173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (plain == NULL) { 1174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(msg); 1175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_build_idr(data, plain, 1178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || 1179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_build_encrypted(data->proposal.encr, 1180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->proposal.integ, 1181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &data->keys, 0, msg, plain, 1182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IKEV2_PAYLOAD_IDr)) { 1183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(plain); 1184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(msg); 1185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(plain); 1188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_update_hdr(msg); 1191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_INIT)", msg); 1193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = SA_AUTH; 1195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->r_sign_msg); 1197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->r_sign_msg = wpabuf_dup(msg); 1198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return msg; 1200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * ikev2_build_sa_auth(struct ikev2_responder_data *data) 1204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *msg, *plain; 1206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* build IKE_SA_AUTH: HDR, SK {IDr, [CERT,] AUTH} */ 1208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1000); 1210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg == NULL) 1211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_build_hdr(data, msg, IKE_SA_AUTH, IKEV2_PAYLOAD_ENCRYPTED, 1); 1213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plain = wpabuf_alloc(data->IDr_len + 1000); 1215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (plain == NULL) { 1216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(msg); 1217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_build_idr(data, plain, IKEV2_PAYLOAD_AUTHENTICATION) || 1221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_build_auth(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || 1222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_build_encrypted(data->proposal.encr, data->proposal.integ, 1223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &data->keys, 0, msg, plain, 1224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IKEV2_PAYLOAD_IDr)) { 1225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(plain); 1226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(msg); 1227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(plain); 1230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_AUTH)", msg); 1232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = IKEV2_DONE; 1234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return msg; 1236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * ikev2_build_notify(struct ikev2_responder_data *data) 1240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *msg; 1242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + 1000); 1244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg == NULL) 1245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->last_msg == LAST_MSG_SA_AUTH) { 1247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* HDR, SK{N} */ 1248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *plain = wpabuf_alloc(100); 1249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (plain == NULL) { 1250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(msg); 1251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_build_hdr(data, msg, IKE_SA_AUTH, 1254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IKEV2_PAYLOAD_ENCRYPTED, 1); 1255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_build_notification(data, plain, 1256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || 1257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_build_encrypted(data->proposal.encr, 1258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->proposal.integ, 1259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &data->keys, 0, msg, plain, 1260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IKEV2_PAYLOAD_NOTIFICATION)) { 1261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(plain); 1262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(msg); 1263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = IKEV2_FAILED; 1266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 1267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* HDR, N */ 1268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_build_hdr(data, msg, IKE_SA_INIT, 1269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IKEV2_PAYLOAD_NOTIFICATION, 0); 1270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_build_notification(data, msg, 1271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) { 1272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(msg); 1273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = SA_INIT; 1276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_update_hdr(msg); 1279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (Notification)", 1281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg); 1282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return msg; 1284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpabuf * ikev2_responder_build(struct ikev2_responder_data *data) 1288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (data->state) { 1290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case SA_INIT: 1291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ikev2_build_sa_init(data); 1292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case SA_AUTH: 1293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ikev2_build_sa_auth(data); 1294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CHILD_SA: 1295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case NOTIFY: 1297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ikev2_build_notify(data); 1298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_DONE: 1299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_FAILED: 1300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1304