static void * eap_gpsk_init(struct eap_sm *sm) { struct eap_gpsk_data *data; data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->state = GPSK_1; data->csuite_count = 0; if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, EAP_GPSK_CIPHER_AES)) { WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, EAP_GPSK_VENDOR_IETF); WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, EAP_GPSK_CIPHER_AES); data->csuite_count++; } if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, EAP_GPSK_CIPHER_SHA256)) { WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, EAP_GPSK_VENDOR_IETF); WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, EAP_GPSK_CIPHER_SHA256); data->csuite_count++; } return data; }
static void * eap_gpsk_init(struct eap_sm *sm) { struct eap_gpsk_data *data; data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->state = GPSK_1; /* TODO: add support for configuring ID_Server */ data->id_server = (u8 *) os_strdup("hostapd"); if (data->id_server) data->id_server_len = os_strlen((char *) data->id_server); data->csuite_count = 0; if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, EAP_GPSK_CIPHER_AES)) { WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, EAP_GPSK_VENDOR_IETF); WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, EAP_GPSK_CIPHER_AES); data->csuite_count++; } if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, EAP_GPSK_CIPHER_SHA256)) { WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, EAP_GPSK_VENDOR_IETF); WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, EAP_GPSK_CIPHER_SHA256); data->csuite_count++; } return data; }
static int eap_gpsk_select_csuite(struct eap_sm *sm, struct eap_gpsk_data *data, const u8 *csuite_list, size_t csuite_list_len) { struct eap_gpsk_csuite *csuite; int i, count; 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_BE32(csuite->vendor); specifier = WPA_GET_BE16(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->forced_cipher || data->forced_cipher == 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"); return -1; } wpa_printf(MSG_DEBUG, "EAP-GPSK: Selected ciphersuite %d:%d", data->vendor, data->specifier); return 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; }