Ejemplo n.º 1
0
static struct wpabuf * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data,
        u8 identifier)
{
    struct wpabuf *resp;
    u8 *rpos, *start;
    size_t mlen;

    wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4");

    mlen = eap_gpsk_mic_len(data->vendor, data->specifier);

    resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, 1 + 2 + mlen,
                         EAP_CODE_RESPONSE, identifier);
    if (resp == NULL)
        return NULL;

    wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_4);
    start = wpabuf_put(resp, 0);

    /* No PD_Payload_3 */
    wpabuf_put_be16(resp, 0);

    rpos = wpabuf_put(resp, mlen);
    if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
                             data->specifier, start, rpos - start, rpos) <
            0) {
        eap_gpsk_state(data, FAILURE);
        wpabuf_free(resp);
        return NULL;
    }

    return resp;
}
static u8 * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, u8 identifier,
				 size_t *respDataLen)
{
	struct eap_hdr *resp;
	u8 *rpos, *start;
	size_t len;

	wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4");

	len = 1 + 2 + eap_gpsk_mic_len(data->vendor, data->specifier);

	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len,
			     EAP_CODE_RESPONSE, identifier, &rpos);
	if (resp == NULL)
		return NULL;

	*rpos++ = EAP_GPSK_OPCODE_GPSK_4;
	start = rpos;

	/* No PD_Payload_3 */
	WPA_PUT_BE16(rpos, 0);
	rpos += 2;

	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
				 data->specifier, start, rpos - start, rpos) <
	    0) {
		eap_gpsk_state(data, FAILURE);
		os_free(resp);
		return NULL;
	}

	return (u8 *) resp;
}
Ejemplo n.º 3
0
static const u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data,
        const u8 *payload,
        const u8 *pos, const u8 *end)
{
    size_t miclen;
    u8 mic[EAP_GPSK_MAX_MIC_LEN];

    if (pos == NULL)
        return NULL;

    miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
    if (end - pos < (int) miclen) {
        wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
                   "(left=%lu miclen=%lu)",
                   (unsigned long) (end - pos),
                   (unsigned long) miclen);
        return NULL;
    }
    if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
                             data->specifier, payload, pos - payload, mic)
            < 0) {
        wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
        return NULL;
    }
    if (os_memcmp(mic, pos, miclen) != 0) {
        wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3");
        wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
        wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
        return NULL;
    }
    pos += miclen;

    return pos;
}
Ejemplo n.º 4
0
static struct wpabuf * eap_gpsk_build_gpsk_3(struct eap_sm *sm,
					     struct eap_gpsk_data *data, u8 id)
{
	u8 *pos, *start;
	size_t len, miclen;
	struct eap_gpsk_csuite *csuite;
	struct wpabuf *req;

	wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3");

	miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
	len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + sm->server_id_len +
		sizeof(struct eap_gpsk_csuite) + 2 + miclen;
	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
			    EAP_CODE_REQUEST, id);
	if (req == NULL) {
		wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory "
			   "for request/GPSK-3");
		eap_gpsk_state(data, FAILURE);
		return NULL;
	}

	wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_3);
	start = wpabuf_put(req, 0);

	wpabuf_put_data(req, data->rand_peer, EAP_GPSK_RAND_LEN);
	wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
	wpabuf_put_be16(req, sm->server_id_len);
	wpabuf_put_data(req, sm->server_id, sm->server_id_len);
	csuite = wpabuf_put(req, sizeof(*csuite));
	WPA_PUT_BE32(csuite->vendor, data->vendor);
	WPA_PUT_BE16(csuite->specifier, data->specifier);

	/* no PD_Payload_2 */
	wpabuf_put_be16(req, 0);

	pos = wpabuf_put(req, miclen);
	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
				 data->specifier, start, pos - start, pos) < 0)
	{
		os_free(req);
		eap_gpsk_state(data, FAILURE);
		return NULL;
	}

	return req;
}
Ejemplo n.º 5
0
static struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data,
        u8 identifier,
        const u8 *csuite_list,
        size_t csuite_list_len)
{
    struct wpabuf *resp;
    size_t len, miclen;
    u8 *rpos, *start;
    struct eap_gpsk_csuite *csuite;

    wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2");

    miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
    len = 1 + 2 + data->id_peer_len + 2 + data->id_server_len +
          2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len +
          sizeof(struct eap_gpsk_csuite) + 2 + miclen;

    resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
                         EAP_CODE_RESPONSE, identifier);
    if (resp == NULL)
        return NULL;

    wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_2);
    start = wpabuf_put(resp, 0);

    wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer",
                      data->id_peer, data->id_peer_len);
    wpabuf_put_be16(resp, data->id_peer_len);
    wpabuf_put_data(resp, data->id_peer, data->id_peer_len);

    wpabuf_put_be16(resp, data->id_server_len);
    wpabuf_put_data(resp, data->id_server, data->id_server_len);

    if (os_get_random(data->rand_peer, EAP_GPSK_RAND_LEN)) {
        wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data "
                   "for RAND_Peer");
        eap_gpsk_state(data, FAILURE);
        wpabuf_free(resp);
        return NULL;
    }
    wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer",
                data->rand_peer, EAP_GPSK_RAND_LEN);
    wpabuf_put_data(resp, data->rand_peer, EAP_GPSK_RAND_LEN);
    wpabuf_put_data(resp, data->rand_server, EAP_GPSK_RAND_LEN);

    wpabuf_put_be16(resp, csuite_list_len);
    wpabuf_put_data(resp, csuite_list, csuite_list_len);

    csuite = wpabuf_put(resp, sizeof(*csuite));
    WPA_PUT_BE32(csuite->vendor, data->vendor);
    WPA_PUT_BE16(csuite->specifier, data->specifier);

    if (eap_gpsk_derive_keys(data->psk, data->psk_len,
                             data->vendor, data->specifier,
                             data->rand_peer, data->rand_server,
                             data->id_peer, data->id_peer_len,
                             data->id_server, data->id_server_len,
                             data->msk, data->emsk,
                             data->sk, &data->sk_len,
                             data->pk, &data->pk_len) < 0) {
        wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys");
        eap_gpsk_state(data, FAILURE);
        wpabuf_free(resp);
        return NULL;
    }

    /* No PD_Payload_1 */
    wpabuf_put_be16(resp, 0);

    rpos = wpabuf_put(resp, miclen);
    if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
                             data->specifier, start, rpos - start, rpos) <
            0) {
        eap_gpsk_state(data, FAILURE);
        wpabuf_free(resp);
        return NULL;
    }

    return resp;
}
Ejemplo n.º 6
0
static void eap_gpsk_process_gpsk_4(struct eap_sm *sm,
				    struct eap_gpsk_data *data,
				    const u8 *payload, size_t payloadlen)
{
	const u8 *pos, *end;
	u16 alen;
	size_t miclen;
	u8 mic[EAP_GPSK_MAX_MIC_LEN];

	if (data->state != GPSK_3)
		return;

	wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-4");

	pos = payload;
	end = payload + payloadlen;

	if (end - pos < 2) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "PD_Payload_1 length");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	alen = WPA_GET_BE16(pos);
	pos += 2;
	if (end - pos < alen) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "PD_Payload_1");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
	pos += alen;

	miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
	if (end - pos < (int) miclen) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
			   "(left=%lu miclen=%lu)",
			   (unsigned long) (end - pos),
			   (unsigned long) miclen);
		eap_gpsk_state(data, FAILURE);
		return;
	}
	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
				 data->specifier, payload, pos - payload, mic)
	    < 0) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	if (os_memcmp_const(mic, pos, miclen) != 0) {
		wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-4");
		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
		eap_gpsk_state(data, FAILURE);
		return;
	}
	pos += miclen;

	if (pos != end) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra "
			   "data in the end of GPSK-4",
			   (unsigned long) (end - pos));
	}

	eap_gpsk_state(data, SUCCESS);
}
Ejemplo n.º 7
0
static void eap_gpsk_process_gpsk_2(struct eap_sm *sm,
				    struct eap_gpsk_data *data,
				    const u8 *payload, size_t payloadlen)
{
	const u8 *pos, *end;
	u16 alen;
	const struct eap_gpsk_csuite *csuite;
	size_t i, miclen;
	u8 mic[EAP_GPSK_MAX_MIC_LEN];

	if (data->state != GPSK_1)
		return;

	wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-2");

	pos = payload;
	end = payload + payloadlen;

	if (end - pos < 2) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "ID_Peer length");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	alen = WPA_GET_BE16(pos);
	pos += 2;
	if (end - pos < alen) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "ID_Peer");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	os_free(data->id_peer);
	data->id_peer = os_malloc(alen);
	if (data->id_peer == NULL) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Not enough memory to store "
			   "%d-octet ID_Peer", alen);
		return;
	}
	os_memcpy(data->id_peer, pos, alen);
	data->id_peer_len = alen;
	wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer",
			  data->id_peer, data->id_peer_len);
	pos += alen;

	if (end - pos < 2) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "ID_Server length");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	alen = WPA_GET_BE16(pos);
	pos += 2;
	if (end - pos < alen) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "ID_Server");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	if (alen != sm->server_id_len ||
	    os_memcmp(pos, sm->server_id, alen) != 0) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and "
			   "GPSK-2 did not match");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	pos += alen;

	if (end - pos < EAP_GPSK_RAND_LEN) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "RAND_Peer");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	os_memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer",
		    data->rand_peer, EAP_GPSK_RAND_LEN);
	pos += EAP_GPSK_RAND_LEN;

	if (end - pos < EAP_GPSK_RAND_LEN) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "RAND_Server");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	if (os_memcmp(data->rand_server, pos, EAP_GPSK_RAND_LEN) != 0) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and "
			   "GPSK-2 did not match");
		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1",
			    data->rand_server, EAP_GPSK_RAND_LEN);
		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-2",
			    pos, EAP_GPSK_RAND_LEN);
		eap_gpsk_state(data, FAILURE);
		return;
	}
	pos += EAP_GPSK_RAND_LEN;

	if (end - pos < 2) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "CSuite_List length");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	alen = WPA_GET_BE16(pos);
	pos += 2;
	if (end - pos < alen) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "CSuite_List");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	if (alen != data->csuite_count * sizeof(struct eap_gpsk_csuite) ||
	    os_memcmp(pos, data->csuite_list, alen) != 0) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List in GPSK-1 and "
			   "GPSK-2 did not match");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	pos += alen;

	if (end - pos < (int) sizeof(*csuite)) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "CSuite_Sel");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	csuite = (const struct eap_gpsk_csuite *) pos;
	for (i = 0; i < data->csuite_count; i++) {
		if (os_memcmp(csuite, &data->csuite_list[i], sizeof(*csuite))
		    == 0)
			break;
	}
	if (i == data->csuite_count) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Peer selected unsupported "
			   "ciphersuite %d:%d",
			   WPA_GET_BE32(csuite->vendor),
			   WPA_GET_BE16(csuite->specifier));
		eap_gpsk_state(data, FAILURE);
		return;
	}
	data->vendor = WPA_GET_BE32(csuite->vendor);
	data->specifier = WPA_GET_BE16(csuite->specifier);
	wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d",
		   data->vendor, data->specifier);
	pos += sizeof(*csuite);	

	if (end - pos < 2) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "PD_Payload_1 length");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	alen = WPA_GET_BE16(pos);
	pos += 2;
	if (end - pos < alen) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
			   "PD_Payload_1");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
	pos += alen;

	if (sm->user == NULL || sm->user->password == NULL) {
		wpa_printf(MSG_INFO, "EAP-GPSK: No PSK/password configured "
			   "for the user");
		eap_gpsk_state(data, FAILURE);
		return;
	}

	if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len,
				 data->vendor, data->specifier,
				 data->rand_peer, data->rand_server,
				 data->id_peer, data->id_peer_len,
				 sm->server_id, sm->server_id_len,
				 data->msk, data->emsk,
				 data->sk, &data->sk_len,
				 data->pk, &data->pk_len) < 0) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys");
		eap_gpsk_state(data, FAILURE);
		return;
	}

	if (eap_gpsk_derive_session_id(sm->user->password,
				       sm->user->password_len,
				       data->vendor, data->specifier,
				       data->rand_peer, data->rand_server,
				       data->id_peer, data->id_peer_len,
				       sm->server_id, sm->server_id_len,
				       EAP_TYPE_GPSK,
				       data->session_id, &data->id_len) < 0) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive Session-Id");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Derived Session-Id",
		    data->session_id, data->id_len);

	miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
	if (end - pos < (int) miclen) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
			   "(left=%lu miclen=%lu)",
			   (unsigned long) (end - pos),
			   (unsigned long) miclen);
		eap_gpsk_state(data, FAILURE);
		return;
	}
	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
				 data->specifier, payload, pos - payload, mic)
	    < 0) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
		eap_gpsk_state(data, FAILURE);
		return;
	}
	if (os_memcmp_const(mic, pos, miclen) != 0) {
		wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-2");
		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
		eap_gpsk_state(data, FAILURE);
		return;
	}
	pos += miclen;

	if (pos != end) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra "
			   "data in the end of GPSK-2",
			   (unsigned long) (end - pos));
	}

	eap_gpsk_state(data, GPSK_3);
}
Ejemplo n.º 8
0
static u8 * eap_gpsk_process_gpsk_3(struct eap_sm *sm,
				    struct eap_gpsk_data *data,
				    struct eap_method_ret *ret,
				    const u8 *reqData, size_t reqDataLen,
				    const u8 *payload, size_t payload_len,
				    size_t *respDataLen)
{
	size_t len, miclen;
	struct eap_hdr *resp;
	u8 *rpos, *start;
	const struct eap_hdr *req;
	const u8 *pos, *end;
	u16 alen;
	int vendor, specifier;
	const struct eap_gpsk_csuite *csuite;
	u8 mic[EAP_GPSK_MAX_MIC_LEN];

	if (data->state != GPSK_3) {
		ret->ignore = TRUE;
		return NULL;
	}

	wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-3");

	req = (const struct eap_hdr *) reqData;
	pos = payload;
	end = payload + payload_len;

	if (end - pos < EAP_GPSK_RAND_LEN) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
			   "RAND_Client");
		return NULL;
	}
	if (os_memcmp(pos, data->rand_client, EAP_GPSK_RAND_LEN) != 0) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Client in GPSK-2 and "
			   "GPSK-3 did not match");
		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Client in GPSK-2",
			    data->rand_client, EAP_GPSK_RAND_LEN);
		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Client in GPSK-3",
			    pos, EAP_GPSK_RAND_LEN);
		eap_gpsk_state(data, FAILURE);
		return NULL;
	}
	pos += EAP_GPSK_RAND_LEN;

	if (end - pos < EAP_GPSK_RAND_LEN) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
			   "RAND_Server");
		return NULL;
	}
	if (os_memcmp(pos, data->rand_server, EAP_GPSK_RAND_LEN) != 0) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and "
			   "GPSK-3 did not match");
		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1",
			    data->rand_server, EAP_GPSK_RAND_LEN);
		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-3",
			    pos, EAP_GPSK_RAND_LEN);
		eap_gpsk_state(data, FAILURE);
		return NULL;
	}
	pos += EAP_GPSK_RAND_LEN;

	if (end - pos < (int) sizeof(*csuite)) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
			   "CSuite_Sel");
		return NULL;
	}
	csuite = (const struct eap_gpsk_csuite *) pos;
	vendor = WPA_GET_BE24(csuite->vendor);
	specifier = WPA_GET_BE24(csuite->specifier);
	pos += sizeof(*csuite);
	if (vendor != data->vendor || specifier != data->specifier) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel (%d:%d) does not "
			   "match with the one sent in GPSK-2 (%d:%d)",
			   vendor, specifier, data->vendor, data->specifier);
		eap_gpsk_state(data, FAILURE);
		return NULL;
	}

	if (end - pos < 2) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
			   "PD_Payload_2 length");
		eap_gpsk_state(data, FAILURE);
		return NULL;
	}
	alen = WPA_GET_BE16(pos);
	pos += 2;
	if (end - pos < alen) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
			   "%d-octet PD_Payload_2", alen);
		eap_gpsk_state(data, FAILURE);
		return NULL;
	}
	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_2", pos, alen);
	pos += alen;
	miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
	if (end - pos < (int) miclen) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
			   "(left=%d miclen=%d)", end - pos, miclen);
		eap_gpsk_state(data, FAILURE);
		return NULL;
	}
	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
				 data->specifier, payload, pos - payload, mic)
	    < 0) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
		eap_gpsk_state(data, FAILURE);
		return NULL;
	}
	if (os_memcmp(mic, pos, miclen) != 0) {
		wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3");
		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
		eap_gpsk_state(data, FAILURE);
		return NULL;
	}
	pos += miclen;

	if (pos != end) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %d bytes of extra "
			   "data in the end of GPSK-2", end - pos);
	}

	wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4");

	len = 1 + 2 + miclen;

	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len,
			     EAP_CODE_RESPONSE, req->identifier, &rpos);
	if (resp == NULL)
		return NULL;

	*rpos++ = EAP_GPSK_OPCODE_GPSK_4;
	start = rpos;

	/* No PD_Payload_3 */
	WPA_PUT_BE16(rpos, 0);
	rpos += 2;

	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
				 data->specifier, start, rpos - start, rpos) <
	    0) {
		eap_gpsk_state(data, FAILURE);
		os_free(resp);
		return NULL;
	}

	eap_gpsk_state(data, SUCCESS);
	ret->methodState = METHOD_DONE;
	ret->decision = DECISION_UNCOND_SUCC;

	return (u8 *) resp;
}
Ejemplo n.º 9
0
static u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm,
				    struct eap_gpsk_data *data,
				    struct eap_method_ret *ret,
				    const u8 *reqData, size_t reqDataLen,
				    const u8 *payload, size_t payload_len,
				    size_t *respDataLen)
{
	size_t len, csuite_list_len, miclen;
	struct eap_hdr *resp;
	u8 *rpos, *start;
	const u8 *csuite_list, *pos, *end;
	const struct eap_hdr *req;
	struct eap_gpsk_csuite *csuite;
	u16 alen;
	int i, count;

	if (data->state != GPSK_1) {
		ret->ignore = TRUE;
		return NULL;
	}

	wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-1");

	req = (const struct eap_hdr *) reqData;
	pos = payload;
	end = payload + payload_len;

	if (end - pos < 2) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet");
		return NULL;
	}
	alen = WPA_GET_BE16(pos);
	pos += 2;
	if (end - pos < alen) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server overflow");
		return NULL;
	}
	os_free(data->id_server);
	data->id_server = os_malloc(alen);
	if (data->id_server == NULL) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: No memory for ID_Server");
		return NULL;
	}
	os_memcpy(data->id_server, pos, alen);
	data->id_server_len = alen;
	wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server",
			  data->id_server, data->id_server_len);
	pos += alen;

	if (end - pos < EAP_GPSK_RAND_LEN) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server overflow");
		return NULL;
	}
	os_memcpy(data->rand_server, pos, EAP_GPSK_RAND_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server",
		    data->rand_server, EAP_GPSK_RAND_LEN);
	pos += EAP_GPSK_RAND_LEN;

	if (end - pos < 2) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet");
		return NULL;
	}
	csuite_list_len = WPA_GET_BE16(pos);
	pos += 2;
	if (end - pos < (int) csuite_list_len) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow");
		return NULL;
	}
	csuite_list = pos;

	if (csuite_list_len == 0 ||
	    csuite_list_len % sizeof(struct eap_gpsk_csuite)) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %d",
			   csuite_list_len);
		return NULL;
	}
	count = csuite_list_len / sizeof(struct eap_gpsk_csuite);
	data->vendor = EAP_GPSK_VENDOR_IETF;
	data->specifier = EAP_GPSK_CIPHER_RESERVED;
	csuite = (struct eap_gpsk_csuite *) csuite_list;
	for (i = 0; i < count; i++) {
		int vendor, specifier;
		vendor = WPA_GET_BE24(csuite->vendor);
		specifier = WPA_GET_BE24(csuite->specifier);
		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite[%d]: %d:%d",
			   i, vendor, specifier);
		if (data->vendor == EAP_GPSK_VENDOR_IETF &&
		    data->specifier == EAP_GPSK_CIPHER_RESERVED &&
		    eap_gpsk_supported_ciphersuite(vendor, specifier)) {
			data->vendor = vendor;
			data->specifier = specifier;
		}
		csuite++;
	}
	if (data->vendor == EAP_GPSK_VENDOR_IETF &&
	    data->specifier == EAP_GPSK_CIPHER_RESERVED) {
		wpa_msg(sm->msg_ctx, MSG_INFO, "EAP-GPSK: No supported "
			"ciphersuite found");
		eap_gpsk_state(data, FAILURE);
		return NULL;
	}
	wpa_printf(MSG_DEBUG, "EAP-GPSK: Selected ciphersuite %d:%d",
		   data->vendor, data->specifier);

	wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2");

	miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
	len = 1 + 2 + data->id_client_len + 2 + data->id_server_len +
		2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len +
		sizeof(struct eap_gpsk_csuite) + 2 + miclen;

	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len,
			     EAP_CODE_RESPONSE, req->identifier, &rpos);
	if (resp == NULL)
		return NULL;

	*rpos++ = EAP_GPSK_OPCODE_GPSK_2;
	start = rpos;

	wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Client",
			  data->id_client, data->id_client_len);
	WPA_PUT_BE16(rpos, data->id_client_len);
	rpos += 2;
	if (data->id_client)
		os_memcpy(rpos, data->id_client, data->id_client_len);
	rpos += data->id_client_len;

	WPA_PUT_BE16(rpos, data->id_server_len);
	rpos += 2;
	if (data->id_server)
		os_memcpy(rpos, data->id_server, data->id_server_len);
	rpos += data->id_server_len;

	if (os_get_random(data->rand_client, EAP_GPSK_RAND_LEN)) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data "
			   "for RAND_Client");
		eap_gpsk_state(data, FAILURE);
		os_free(resp);
		return NULL;
	}
	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Client",
		    data->rand_client, EAP_GPSK_RAND_LEN);
	os_memcpy(rpos, data->rand_client, EAP_GPSK_RAND_LEN);
	rpos += EAP_GPSK_RAND_LEN;

	os_memcpy(rpos, data->rand_server, EAP_GPSK_RAND_LEN);
	rpos += EAP_GPSK_RAND_LEN;

	WPA_PUT_BE16(rpos, csuite_list_len);
	rpos += 2;
	os_memcpy(rpos, csuite_list, csuite_list_len);
	rpos += csuite_list_len;

	csuite = (struct eap_gpsk_csuite *) rpos;
	WPA_PUT_BE24(csuite->vendor, data->vendor);
	WPA_PUT_BE24(csuite->specifier, data->specifier);
	rpos = (u8 *) (csuite + 1);

	if (eap_gpsk_derive_keys(data->psk, data->psk_len,
				 data->vendor, data->specifier,
				 data->rand_client, data->rand_server,
				 data->id_client, data->id_client_len,
				 data->id_server, data->id_server_len,
				 data->msk, data->emsk,
				 data->sk, &data->sk_len,
				 data->pk, &data->pk_len) < 0) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys");
		eap_gpsk_state(data, FAILURE);
		os_free(resp);
		return NULL;
	}

	/* No PD_Payload_1 */
	WPA_PUT_BE16(rpos, 0);
	rpos += 2;

	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
				 data->specifier, start, rpos - start, rpos) <
	    0) {
		eap_gpsk_state(data, FAILURE);
		os_free(resp);
		return NULL;
	}

	eap_gpsk_state(data, GPSK_3);

	return (u8 *) resp;
}
static u8 * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, u8 identifier,
				 const u8 *csuite_list, size_t csuite_list_len,
				 size_t *respDataLen)
{
	struct eap_hdr *resp;
	size_t len, miclen;
	u8 *rpos, *start;
	struct eap_gpsk_csuite *csuite;

	wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2");

	miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
	len = 1 + 2 + data->id_peer_len + 2 + data->id_server_len +
		2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len +
		sizeof(struct eap_gpsk_csuite) + 2 + miclen;

	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len,
			     EAP_CODE_RESPONSE, identifier, &rpos);
	if (resp == NULL)
		return NULL;

	*rpos++ = EAP_GPSK_OPCODE_GPSK_2;
	start = rpos;

	wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer",
			  data->id_peer, data->id_peer_len);
	WPA_PUT_BE16(rpos, data->id_peer_len);
	rpos += 2;
	if (data->id_peer)
		os_memcpy(rpos, data->id_peer, data->id_peer_len);
	rpos += data->id_peer_len;

	WPA_PUT_BE16(rpos, data->id_server_len);
	rpos += 2;
	if (data->id_server)
		os_memcpy(rpos, data->id_server, data->id_server_len);
	rpos += data->id_server_len;

	if (os_get_random(data->rand_peer, EAP_GPSK_RAND_LEN)) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data "
			   "for RAND_Peer");
		eap_gpsk_state(data, FAILURE);
		os_free(resp);
		return NULL;
	}
	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer",
		    data->rand_peer, EAP_GPSK_RAND_LEN);
	os_memcpy(rpos, data->rand_peer, EAP_GPSK_RAND_LEN);
	rpos += EAP_GPSK_RAND_LEN;

	os_memcpy(rpos, data->rand_server, EAP_GPSK_RAND_LEN);
	rpos += EAP_GPSK_RAND_LEN;

	WPA_PUT_BE16(rpos, csuite_list_len);
	rpos += 2;
	os_memcpy(rpos, csuite_list, csuite_list_len);
	rpos += csuite_list_len;

	csuite = (struct eap_gpsk_csuite *) rpos;
	WPA_PUT_BE32(csuite->vendor, data->vendor);
	WPA_PUT_BE16(csuite->specifier, data->specifier);
	rpos = (u8 *) (csuite + 1);

	if (eap_gpsk_derive_keys(data->psk, data->psk_len,
				 data->vendor, data->specifier,
				 data->rand_peer, data->rand_server,
				 data->id_peer, data->id_peer_len,
				 data->id_server, data->id_server_len,
				 data->msk, data->emsk,
				 data->sk, &data->sk_len,
				 data->pk, &data->pk_len) < 0) {
		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys");
		eap_gpsk_state(data, FAILURE);
		os_free(resp);
		return NULL;
	}

	/* No PD_Payload_1 */
	WPA_PUT_BE16(rpos, 0);
	rpos += 2;

	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
				 data->specifier, start, rpos - start, rpos) <
	    0) {
		eap_gpsk_state(data, FAILURE);
		os_free(resp);
		return NULL;
	}

	return (u8 *) resp;
}