📄 wps_enrollee.c
字号:
/*
* WPS_ENROLLEE.C : WPS ENROLLEE Porcess Module
*
* ver date author comment
* 0.0.1 06/08/27 Gao Hua First
* 0.0.2 07/09/05 D.W.Yan Refactor code
*/
#include "wps_types.h"
#include "wps_common.h"
#include "wps_osfunc.h"
#include "wps_crypto.h"
#include "wps_wlandrv.h"
#include "wps_lib.h"
#include "wps_eap_pkt.h"
#include "wps_data_element.h"
#include "wps_callback.h"
#include "wps_enrollee.h"
#define SEND_BUFFER_SIZE (800)
///////////////////////////////////////////////////////////////////////////
static const WPS_char
g_rnd_seed[] = "enrollee string to make the random number generator think it has entropy";
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
static void wps_enrol_save_credential(struct enrollee* enrollee,
WPS_u8 *Attribute);
static WPS_s32 wps_enrol_build_enc_set(struct enrollee *enrollee,
const WPS_u8 *DataToEncrypt,
WPS_s32 DataLen, WPS_u8 *Output,
WPS_s32 OutputBuffLen);
static WPS_s32 wps_enrol_analyze_enc_set(struct enrollee *enrollee,
const WPS_u8 *Input, WPS_s32 InputLen,
WPS_u8 *Output, WPS_s32 OutputBuffLen);
static WPS_s32 wps_enrol_key_derivation(struct enrollee *enrollee);
static WPS_s32 wps_enrol_check_rh1_using_rsn1(struct enrollee *enrollee);
static WPS_s32 wps_enrol_check_rh2_using_rsn2(struct enrollee *enrollee);
static WPS_s32 wps_enrol_upt_last_msg_for_snd(struct enrollee *enrollee,
WPS_u8 *SendBuff,
WPS_s16 MessageLength);
static WPS_s32 wps_enrol_upt_last_msg_for_rcv(struct enrollee *enrollee,
struct eap_packet *packet);
static WPS_s32 wps_enrol_snd_m1(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_m3(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_m5(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_m7(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_ack(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_nack(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_done(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_eap_fail(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_eap_rsp_ident(struct enrollee *enrollee);
static WPS_s32 wps_enrol_rcv_start(struct enrollee *enrollee,
struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_m2(struct enrollee *enrollee,
struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_m2d(struct enrollee *enrollee,
struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_m4(struct enrollee *enrollee,
struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_m6(struct enrollee *enrollee,
struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_m8(struct enrollee *enrollee,
struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_nack(struct enrollee *enrollee,
struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_eap_req_ident(struct enrollee *enrollee,
struct eap_packet *packet);
void wps_enrol_save_credential(struct enrollee* enrollee, WPS_u8 *Attribute)
{
WPS_u8 *p = Attribute;
int count;
ENROLLEE_CREDENTIAL tmp_credential;
WPS_u8 *CredentialStart;
WPS_s16 CredentialDataLen;
WPS_s16 DataLen;
#if ENROLLEE_DEBUG
WPS_s16 i;
#endif
for (count = 0; ; count++) {
CredentialStart = p;
if (WPS_get_word(p) == WPS_h2n16(E_Credential_ID)) {
CredentialDataLen = WPS_n2h16(WPS_get_word(p+2));
p += 2+2;
}
else {
break;
}
#if ENROLLEE_DEBUG
WPS_PRINTF("\n-----------WLAN Credential(%d) information in M8----------\n", count+1);
#endif
if (WPS_get_word(p) == WPS_h2n16(E_NetworkIndex_ID)&& WPS_get_word(p+2)
== WPS_h2n16(E_NetworkIndex_Length)) {
#if ENROLLEE_DEBUG
WPS_PRINTF("\tNetwork Index:\t\t%d\n", *(p+4));
#endif
tmp_credential.Cre_NetworkIndex = *(p+4);
p += 2+2+1;
}
else {
WPS_PRINTF("Enrollee: Credential format is invalid.\n");
return;
}
if (WPS_get_word(p) == WPS_h2n16(E_SSID_ID)&& WPS_n2h16(WPS_get_word(p+2))
<= E_SSID_MaxLength) {
DataLen = WPS_n2h16(WPS_get_word(p+2));
#if ENROLLEE_DEBUG
WPS_PRINTF("\tSSID:\t\t\t");
for (i=0; i<DataLen; i++) {
WPS_PRINTF("\t%c", *(p+4+i));
}
WPS_PRINTF("\n");
#endif
WPS_MEM_FILL(tmp_credential.Cre_SSID, 0, E_SSID_MaxLength);
WPS_MEM_CPY(tmp_credential.Cre_SSID, p+4, DataLen);
tmp_credential.Cre_SSID_Length = DataLen;
p += 2+2+DataLen;
}
else {
WPS_PRINTF("Enrollee: Credential format is invalid.\n");
return;
}
if (WPS_get_word(p) == WPS_h2n16(E_AuthenticationType_ID)&& WPS_get_word(p
+2) == WPS_h2n16(E_AuthenticationType_Length)) {
#if ENROLLEE_DEBUG
WPS_PRINTF("\tAuthentication Type:\t");
switch (WPS_n2h16(WPS_get_word(p+4))) {
case AUTHENTICATION_TYPE_OPEN:
WPS_PRINTF("\tOPEN");
break;
case AUTHENTICATION_TYPE_WPAPSK:
WPS_PRINTF("\tWPAPSK");
break;
case AUTHENTICATION_TYPE_SHARED:
WPS_PRINTF("\tSHARED");
break;
case AUTHENTICATION_TYPE_WPA:
WPS_PRINTF("\tWPA");
break;
case AUTHENTICATION_TYPE_WPA2:
WPS_PRINTF("\tWPA2");
break;
case AUTHENTICATION_TYPE_WPA2PSK:
WPS_PRINTF("\tWPA2PSK");
break;
default:
break;
}
WPS_PRINTF("\n");
#endif
tmp_credential.Cre_AuthenticationType = WPS_n2h16(WPS_get_word(p+4));
p += 2+2+E_AuthenticationType_Length;
}
else {
WPS_PRINTF("Enrollee: Credential format is invalid.\n");
return;
}
if (WPS_get_word(p) == WPS_h2n16(E_EncryptionType_ID)&& WPS_get_word(p+2)
== WPS_h2n16(E_EncryptionType_Length)) {
#if ENROLLEE_DEBUG
WPS_PRINTF("\tEncryption Type:\t");
switch (WPS_n2h16(WPS_get_word(p+4))) {
case ENCRYPTION_TYPE_NONE:
WPS_PRINTF("\tNONE");
break;
case ENCRYPTION_TYPE_WEP:
WPS_PRINTF("\tWEP");
break;
case ENCRYPTION_TYPE_TKIP:
WPS_PRINTF("\tTKIP");
break;
case ENCRYPTION_TYPE_AES:
WPS_PRINTF("\tAES");
break;
default:
break;
}
WPS_PRINTF("\n");
#endif
tmp_credential.Cre_EncryptionType = WPS_n2h16(WPS_get_word(p+4));
p += 2+2+E_EncryptionType_Length;
}
else {
WPS_PRINTF("Enrollee: Credential format is invalid.\n");
return;
}
//
// Optional elemnet: Network Key Index
//
if (WPS_get_word(p) == WPS_h2n16(E_NetworkKeyIndex_ID)
&& WPS_n2h16(WPS_get_word(p+2)) == E_NetworkKeyIndex_Length) {
#if ENROLLEE_DEBUG
WPS_PRINTF("\tNetwork Key Index:\t%d\n", *(p+4));
#endif
tmp_credential.Cre_NetworkKeyIndex = *(p+4);
p += 2+2+E_NetworkKeyIndex_Length;
}
if (WPS_get_word(p) == WPS_h2n16(E_NetworkKey_ID)
&& WPS_n2h16(WPS_get_word(p+2)) <= E_NetworkKey_MaxLength) {
DataLen = WPS_n2h16(WPS_get_word(p+2));
#if ENROLLEE_DEBUG
if (DataLen > 0) {
WPS_PRINTF("\tNetwork Key:\t\t");
for (i=0; i<DataLen; i++) {
WPS_PRINTF("\t%x", *(p+4+i));
}
WPS_PRINTF("\n");
}
#endif
if (DataLen > 0) {
WPS_MEM_FILL(tmp_credential.Cre_NetworkKey, 0, E_NetworkKey_MaxLength);
WPS_MEM_CPY(tmp_credential.Cre_NetworkKey, p+4, DataLen);
}
tmp_credential.Cre_NetworkKey_Length = DataLen;
p += 2+2+DataLen;
}
else {
WPS_PRINTF("Enrollee: Credential format is invalid.\n");
return;
}
if (WPS_get_word(p) == WPS_h2n16(E_MACAddress_ID)&& WPS_get_word(p+2)
== WPS_h2n16(E_MACAddress_Length)) {
#if ENROLLEE_DEBUG
WPS_PRINTF("\tMAC Address:\t\t");
for (i=0; i<E_MACAddress_Length; i++) {
WPS_PRINTF("\t%x ", *(p+4+i));
}
WPS_PRINTF("\n");
#endif
WPS_MEM_CPY(tmp_credential.Cre_MACAddress, p+4, E_MACAddress_Length);
p += 2+2+E_MACAddress_Length;
}
else {
WPS_PRINTF("Enrollee: Credential format is invalid.\n");
return;
}
//
// Optional elemnet: EAP Type
//
if (WPS_get_word(p) == WPS_h2n16(E_EAPType_ID)
&& WPS_n2h16(WPS_get_word(p+2)) <= E_EAPType_MaxLength) {
DataLen = WPS_n2h16(WPS_get_word(p+2));
#if ENROLLEE_DEBUG
WPS_PRINTF("\tEAP Type:\t\t");
for (i=0; i<DataLen; i++) {
WPS_PRINTF("\t%x", *(p+4+i));
}
WPS_PRINTF("\n");
#endif
p += 2+2+DataLen;
}
//
// Optional elemnet: EAP Identity
//
if (WPS_get_word(p) == WPS_h2n16(E_EAPIdentity_ID)
&& WPS_n2h16(WPS_get_word(p+2)) <= E_EAPIdentity_MaxLength) {
DataLen = WPS_n2h16(WPS_get_word(p+2));
#if ENROLLEE_DEBUG
WPS_PRINTF("\tEAP Identity:\t\t");
for (i=0; i<DataLen; i++) {
WPS_PRINTF("\t%x", *(p+4+i));
}
WPS_PRINTF("\n");
#endif
p += 2+2+DataLen;
}
//
// Optional elemnet: Key Provided Automatically
//
if (WPS_get_word(p) == WPS_h2n16(E_KeyProvidedAutomatically_ID)
&& WPS_n2h16(WPS_get_word(p+2)) == E_KeyProvidedAutomatically_Length) {
#if ENROLLEE_DEBUG
if (WPS_BOOL_LENGTH == 4) {
WPS_PRINTF("\tKey Provided Automatically:\t%x\n",
WPS_get_dword(p+4));
}
else if (WPS_BOOL_LENGTH == 2) {
WPS_PRINTF("\tKey Provided Automatically:\t%x\n", WPS_get_word(p+4));
}
else /* 1 byte */
{
WPS_PRINTF("\tKey Provided Automatically:\t%x\n", *(p+4));
}
#endif
p += 2+2+E_KeyProvidedAutomatically_Length;
}
//
// Optional elemnet: 802.1X Enabled
//
if (WPS_get_word(p) == WPS_h2n16(E_8021xEnabled_ID)
&& WPS_n2h16(WPS_get_word(p+2)) == E_8021xEnabled_Length) {
#if ENROLLEE_DEBUG
if (WPS_BOOL_LENGTH == 4) {
WPS_PRINTF("\t802.1X Enabled:\t%x\n", WPS_get_dword(p+4));
}
else if (WPS_BOOL_LENGTH == 2) {
WPS_PRINTF("\t802.1X Enabled:\t%x\n", WPS_get_word(p+4));
}
else /* 1 byte */
{
WPS_PRINTF("\t802.1X Enabled:\t%x\n", *(p+4));
}
#endif
p += 2+2+E_8021xEnabled_Length;
}
if (tmp_credential.Cre_SSID_Length == enrollee->Current_SSID_Length &&
WPS_MEM_CMP(tmp_credential.Cre_SSID, enrollee->Current_SSID, tmp_credential.Cre_SSID_Length) == 0) {
enrollee->credential = tmp_credential;
WPS_PRINTF("Credential selected!!!\n");
}
#if ENROLLEE_DEBUG
WPS_PRINTF("----------------------------------------------------------\n\n");
#endif
p = CredentialStart+2+2+CredentialDataLen;
}
//
// Optional elemnet: New Password
//
if (WPS_get_word(p) == WPS_h2n16(E_NewPassword_ID)
&& WPS_n2h16(WPS_get_word(p+2)) <= E_NewPassword_MaxLength) {
DataLen = WPS_n2h16(WPS_get_word(p+2));
#if ENROLLEE_DEBUG
WPS_PRINTF("\tNew Password:\t\t");
for (i=0; i<DataLen; i++) {
WPS_PRINTF("\t%x", *(p+4+i));
}
WPS_PRINTF("\n");
#endif
p += 2+2+DataLen;
}
//
// Optional elemnet: Device Password ID
//
if (WPS_get_word(p) == WPS_h2n16(E_DevicePasswordID_ID)
&& WPS_n2h16(WPS_get_word(p+2)) == E_DevicePasswordID_Length) {
#if ENROLLEE_DEBUG
WPS_PRINTF("\tDevice Password ID:\t%x\n", WPS_n2h16(WPS_get_word(p+4)));
#endif
p += 2+2+E_DevicePasswordID_Length;
}
}
//
// Parameters:
// DataToEncrypt: a set of Simple Config TLV attributes excluding the Key Wrap Authenticator attribute
// Output: the point of target buffer to put the Encrypted Settings attribute
// Return values:
// 0: Successful.
// -1: Failed to build the Encrypted Settings attribute.
//
WPS_s32 wps_enrol_build_enc_set(struct enrollee *enrollee, const WPS_u8 *DataToEncrypt, WPS_s32 DataLen, WPS_u8 *Output, WPS_s32 OutputBuffLen)
{
WPS_s16 AES_Input_Length = DataLen+2+2+E_KeyWrapAuthenticator_Length+16;
if (OutputBuffLen < (4+16+AES_Input_Length))
{
WPS_PRINTF("BuildEncryptedSettings(): Output buffer is too small!\n");
return -1;
}
WPS_set_word(Output, WPS_h2n16(E_EncryptedSettings_ID));
WPS_set_word(Output+2, WPS_h2n16(16+AES_Input_Length));
WPS_u8 *IV = Output+4;
WPS_Rand(IV, 16);
WPS_u8 *temp = (WPS_u8 *)WPS_MALLOC(AES_Input_Length);
WPS_MEM_CPY(temp, DataToEncrypt, DataLen);
WPS_u8 HMAC_Output[32];
WPS_HMAC_Sha256(enrollee->AuthKey, 32, temp, DataLen, HMAC_Output, 32);
WPS_set_word((temp+DataLen), WPS_h2n16(E_KeyWrapAuthenticator_ID));
WPS_set_word((temp+DataLen+2), WPS_h2n16(E_KeyWrapAuthenticator_Length));
WPS_MEM_CPY(temp+DataLen+2+2, HMAC_Output, E_KeyWrapAuthenticator_Length);
WPS_MEM_FILL(temp+DataLen+2+2+E_KeyWrapAuthenticator_Length, 0x10, 16);
WPS_u8 IV_temp[16];
WPS_MEM_CPY(IV_temp, IV, 16);
WPS_AES_CBC_Encrypt(enrollee->KeyWrapKey, 16, IV_temp, 16, temp, AES_Input_Length, Output+4+16, AES_Input_Length);
WPS_MFREE(temp);
return 0;
}
//
// Parameters:
// Input: the point of the input Encrypted Settings attribute to be analyzed
// Output: the point of target buffer to put the decrypted result
// Return values:
// 0: Analyzed successfully, the decrypted result is copied to Output buffer.
// -1: HMAC-SHA256 checksum failed.
//
WPS_s32 wps_enrol_analyze_enc_set(struct enrollee *enrollee, const WPS_u8 *Input, WPS_s32 InputLen, WPS_u8 *Output, WPS_s32 OutputBuffLen)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -