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; }
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 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); }
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; }