《深入理解Android:Wi-Fi,NFC和GPS》章节连载[节选]--第六章 深入理解wi-Fi Simple Configuration

时间:2014-03-20 00:06:57   收藏:0   阅读:618

首先感谢各位兄弟姐妹们的耐心等待。本书预计在4月上市发售。从今天开始,我将在博客中连载此书的一些内容。注意,此处连载的是未经出版社编辑的原始稿件,所以样子会有些非专业。

注意,如下是本章目录,本文节选6.1~6.2.3.1,6.2.3.5~最后节

 

为了方便读者深入学习,本系列连载都会将作者研究过程中所学习的

参考文献列出来

 

                          第6章  深入理解Wi-Fi Simple Configuration

bubuko.com,布布扣

本章主要内容:

6.1  概述

Wi-Fi相关技术体系中,除了802.11定义的标准规范外,Wi-Fi AllianceWi-Fi联盟)也推出了两项比较重要的技术规范,他们分别是Wi-Fi Simple ConfigurationWi-Fi P2P。其中:

注意,P2P和第3章无线网络结构中提到的Independent BSS完全不同。IBSS中,各个STA属于完全对等的关系,而P2P则不然。关于P2P的细节,我们留待下章再来分析。

wpa_supplicant(以后简称WPAS)中,WSC的功能点分散在第4章介绍的几条分析路线中,为了避免赘述,本章的分析拟采用如下方法:

下面,先来介绍WSC的理论知识。

6.2  WSC基础知识介绍

WSC规范早期的名字叫Wi-Fi Protected Setup(简写为WPS)。WFA推出WPA后不久,WPS规范便被推出。随着WPA2的出现,WFA又制订了WPS的升级版,即WSCWSC的规范(以2.0.2版为例)全文只有150来页。

WSC的目的很简单,就是为了简化无线网络配置(这也是其英文名为Simple Configuration的原因)。本节将以WSC的技术规范为主,向读者介绍相关的理论知识。

提示:WSC规范中,安全设置信息可以借助Wi-Fi作为传输手段,也可以借助其他传输方式,如NFC传输等。如果这些信息使用Wi-Fi作为传输手段,则称为In-Band交换,否则称为Out-of-Band交换。

6.2.1  WSC应用场景介绍[1]

WSC定义两个应用场景(usage model),分别是Primary UMSecondary UM,其中:

Primary UM常见的两种案例包括PINPBC。其中,PIN对应的使用案例可用图6-1来表示:

bubuko.com,布布扣

6-1  WSC PIN案例示意

6-1所示为WSC定义的PIN码配置方法,其工作流程为:

1)打开APSTA。用户首先从STA相关的设置选项中获取一个PIN码。

2)然后用户将STAPIN码通过AP的设置页面传递给AP

3APSTA将基于这个PIN码完成安全设置协商。然后STA将完成扫描、关联、四次握手等工作以加入目标AP

PIN码是一个长度为8个数字的字符串,图6-2所示为笔者用Galaxy Note2测试WSC PIN方法时获取到的PIN信息。

bubuko.com,布布扣

6-2  Galaxy Note2 WSC PIN设置

6-2左图所示的页面位于Settings的无线网络设置选项中,有条件的读者不妨一试。

STA中的PIN码需要输入到AP中,图6-3所示为笔者家中无线路由器WSC PIN设置页面,注意右下角的黑框(里边填写了来自手机的PIN码,笔者测试时从Galaxy Note2中获取的PIN码是33871042)。

bubuko.com,布布扣

6-3  AP设置页面

提示:图6-2和图6-3中所示的PIN码并不一致。此处为笔者有意为之,表示系统每次生成的PIN码不是固定的。

相比PIN而言,PB配置方法(Push Button Configuration,简称PBC)的使用更加简单。图6-4所示为PBC案例示意图。

bubuko.com,布布扣

6-4  PBC案例示意图

由图6-4可知,PBC的工作流程如下:

1)用户打开AP和打印机(支持Wi-Fi)。打印机和AP上都有一个小按钮(注意,规范要求该按钮必须标记上WPS以表示它对WSC的支持)。

2)用户只要在AP和打印机上摁一下该按钮,该操作将触发打印机和AP完成安全设置协商。如此,打印机获取AP的安全设置信息后将顺利加入目标AP

6-5所示为笔者家中无线路由器上的WSC按钮。

bubuko.com,布布扣

6-5  PBC实物

对于Android智能手机,它可通过软件中的按钮来模拟真实的Push Button(参考图6-2中左图的“WPS推送按钮”项)。

6.2.2  WSC核心组件及接口介绍[2]

WSC规范定义了三个核心组件,如图6-6所示:

bubuko.com,布布扣

6-6  WSC核心组件

6-6所示为WSC定义的三个核心组件,其中:

注意,这三个组件只是逻辑上的概念。在具体实现时,APRegistrar可以由同一个实体实现,也可分别由不同实体来实现。

1)日常生活中,支持WSC的无线路由器兼具APRegistrar的功能。这种AP在规范中被称为Standalone APAndroid智能手机扮演Enrollee的角色。

2)如果APRegistrar分别由不同实体来实现,这种Registrar也被称为External Registrar

除了三大组件之外,规范还定义了组件之间的交互接口。例如图6-6中的EMA代表三个核心组件之间交互的接口,这些接口定义了交互双方需要实现的一些功能。

规范中关于EMA的介绍非常复杂,笔者不拟照搬规范的内容,而是试图通过一种普适的case来介绍EMA的功能。这个case就是APRegistrar组件实现于一个无线路由器中,即Standalone AP,而EnrolleeSTA实现。STAStandalone AP通过Wi-Fi传输数据,即它们将采用In-Band交互手段。

在上述情况下,STA中的Interface E包括的功能有:

Standalone APInterface E包括的功能有:

另外,STAAP可选择实现某种Out-of-Band交互手段,规范中提到的两种手段包括NFCUSB

对于Interface A来说:

由于Standalone AP已经集成了三大组件中的APRegistrar,所以Interface M的功能几乎简化为0。由于本书不讨论AP的实现,所以此处不拟介绍和它相关的内容。

规范阅读提示:WSC规范关于EMA的介绍比较复杂,其中还涉及到UPnP的使用。笔者不拟讨论UPnP方面的内容。对它感兴趣的读者不妨参考笔者的一篇博文:http://blog.csdn.net/innost/article/details/7078539

由上文所述内容可知,WSC的核心知识集中在WSC IE以及RP协议中,下面将单独用一节来介绍它们。

6.2.3  Registration Protocol介绍[3]

以前面提到的普适case为例,当STAStandalone AP采用In-Band交互方法时,RP协议的完整交互流程如图6-7所示:

bubuko.com,布布扣

6-7  完整RP协议交互示意图

6-3中包括两个部分,由“Enter passworkd of Enrollee”行隔开,其中:

关于图6-7所涉及的流程,笔者特别强调几点,请读者认真体会:

根据上面的描述,我们可知:

WSC的核心工作就是帮助STAAP完成安全配置信息协商。由于在这个流程中,用户只需输入PIN码或摁按钮,所以用户的工作量极小。WSC工作完成后,STAAP的工作就和第4章介绍的一样了(STA首先关联到AP,然后完成4次握手协议和Group Handshake协议)。

下面我们将分别介绍WSC IE以及EAP-WSC相关知识。首先登场的是WSC IE

1.  WSC IEAttribute介绍[4]

WSC IE并不属于802.11规范所定义的IE,而是属于Vendor定义的IE。根据802.11规范,Vendor定义的IE有着如图6-8所示的组成结构:

bubuko.com,布布扣

6-8  Vendor IE的结构

根据图6-8所示的结构,WSC IE对应的设置如下:

6-9所示为笔者截获的WSC IE示意图。

bubuko.com,布布扣

6-9  WSC IE实例

由上文可知,WSC IE的核心是其携带的Attribute

WSC规范定义了多个Attribute,而了解这些Attribute的内容及作用是学习WSC的必经之路。下面将介绍WSC中一些重要的Attribute

提示:Attribute不仅被WSC IE使用,还被后文介绍的EAP-WSC包使用

 

===================略略略略略略略==============================

 

5.  EAP-WSC处理流程分析

EAP-WSC流程涉及到EAPOL中的四个状态机(SUPP_PAEKEY_RXSUPP_BEPort Timers)以及EAP SM之间的联动。当STA成功关联到AP后,EAPOLEAP状态机情况如下(详情请参考第44.5.3.4.3eapol_sm_notify_portEnabled分析”一节):

  • SUPP_PAEDISCONNECTED状态、KEY_RXNO_KEY_RECEIVE状态、SUPP_BEIDLE状态、EAP_SMDISABLED状态。

根据6.2.3Registration Protocol介绍”一节中的图6-7EAP-WSC流程的开始于STAAP发送的EAPOL-Start帧。是什么原因导致STA发送EAPOL-Start帧呢?来看下文。

1  发送EAPOL-Start

STA关联到AP流程的最后,eapol_sm_notify_portEnabled将设置portEnabled1,根据代码(eapol_supp_sm.cSM_STEP(SUPP_PAE))以及第4章图4-28Supplicant PAE SM状态示意图)可知,SUPP_PAE下一个要进入的状态是CONNECTING,其EAEntry Aciton)代码为:

[-->eapol_supp_sm.c::SM_STATE(SUPP_PAE, CONNECTING)]

SM_STATE(SUPP_PAE, CONNECTING)

{

    //SUPP_PAE_state此时的值为SUPP_PAE_DISCONNECTED,故send_start为0

    //下面注意这个判断很重要,我们待会还会回到此处

    int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING;

    SM_ENTRY(SUPP_PAE, CONNECTING);

    if (send_start) {

        sm->startWhen = sm->startPeriod;

        sm->startCount++;

    } else {

 #ifdef CONFIG_WPS  //

        sm->startWhen = 1; //注意,如果WPAS支持WPS,则startWhen值为1

#else /* CONFIG_WPS */

        sm->startWhen = 3;

#endif /* CONFIG_WPS */

    }

    //启动Port Timers SM,Port Timers SM将递减startWhen,并调用eapol_sm_step以重新遍历状态机

    eapol_enable_timer_tick(sm);

    sm->eapolEap = FALSE; ..

    //由于send_start为0,所以此时还不会发送EAPOL-Start包

    if (send_start)  eapol_sm_txStart(sm);

}

根据代码中的注释,当Port Timers SM运行时,它将递减startWhen变量(结果是startWhen的值变为0),然后通过eapol_sm_step重新遍历状态机。在该函数中,PAESM_STEP将被调用以检查是否需要进行状态切换,相关代码如下所示:

[-->eapol_supp_sm.c::SM_STEP(SUPP_PAE)]

SM_STEP(SUPP_PAE)

{

    ......//略去不相关的内容

    else switch (sm->SUPP_PAE_state) { //SUPP_PAE_state还处于CONNECTING状态

      ......

        case SUPP_PAE_CONNECTING:

        if (sm->startWhen == 0 && sm->startCount < sm->maxStart)

            SM_ENTER(SUPP_PAE, CONNECTING);//由于startWhen为0,PAE将重新进入CONNECTING状态

         ......

        break;

    case SUPP_PAE_AUTHENTICATING:

    ......

   }

}

根据上面代码可知,PAE将再次从CONNECTING状态进入CONNECTING状态。请读者回顾SM_STATE(SUPP_PAE, CONNECTING)函数。这一次sendStart将取值1,所以eapol_sm_txStart会被调用。该函数的代码如下所示:

[-->eapol_supp_sm.c::eapol_sm_txStart]

static void eapol_sm_txStart(struct eapol_sm *sm)

{

    //eapol_send函数指针指向wpa_supplicant_eapol_send,相关代码在wpas_glue.c中。请读者自行阅读

    sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);

    sm->dot1xSuppEapolStartFramesTx++;

    sm->dot1xSuppEapolFramesTx++;

}

由上述代码可知,eapol_send的实例wpa_supplicant_eapol_send将最终发送EAPOL-Start帧。

2  状态机切换处理介绍

STA发出EAPOL-Start后,AP将发送EAP-Request/Identity包。STA处理EAP-Request/Identity后将回复EAP-Response/Identity包。上述流程将触发EAPOL中的PAEBEEAP状态机联动。此联动过程相当复杂。故本节将以EAP-Request/Identity为入口,分析WPAS中状态机的切换处理。

注意:此处的状态机联动实际上反映的是WPASEAP包处理的通用流程。学习过程中,请读者务必结合第44.4EAPEAPOL模块介绍”一节介绍的理论知识。

先来看EAP-Request的处理。WPAS中,EAP包接收的函数是wpa_supplicant_rx_eapol(相关分析请参考第44.5.3.5EAPOL-Key交换流程分析”一节对wpa_supplicant_rx_eapol的介绍)。在那里,我们说过非PSK认证方法将由eapol_sm_rx_eapol处理。故直接来看eapol_sm_rx_eapol函数,代码如下所示:

[-->eapol_supp_sm.c::eapol_sm_rx_eapol]

int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, size_t len)

{

    const struct ieee802_1x_hdr *hdr;  const struct ieee802_1x_eapol_key *key;

    int data_len;  int res = 1; size_t plen;

 

    sm->dot1xSuppEapolFramesRx++;

    hdr = (const struct ieee802_1x_hdr *) buf;

    sm->dot1xSuppLastEapolFrameVersion = hdr->version;

    os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);

   

    plen = be_to_host16(hdr->length);

    ......

#ifdef CONFIG_WPS

    //workaround中文意思为“变通方案”。在WPAS中,它表示为了兼容某些AP的错误行为(例如发送的EAP包

    //格式不符合要求),而采用绕过去的方法来处理

    if (sm->conf.workaround && plen < len - sizeof(*hdr) &&

        hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&

        len - sizeof(*hdr) > sizeof(struct eap_hdr)) {

          ......

     }

#endif

    data_len = plen + sizeof(*hdr);

    switch (hdr->type) {

    case IEEE802_1X_TYPE_EAP_PACKET:  //本例中,我们收到的是EAP-Request包,满足此case条件

        ......

        wpabuf_free(sm->eapReqData);

        sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen);

        if (sm->eapReqData) {

            sm->eapolEap = TRUE;  //设置条件变量

            eapol_sm_step(sm); //触发状态机运行

        }

        break;

        ......

    }

 

    return res;

}

WPAS每收到一个EAP包都会触发上述代码中流程。回顾一下eapol_sm_step中和状态机运转相关的代码:

[-->eapol_supp_sm.c::eapol_sm_step]

void eapol_sm_step(struct eapol_sm *sm)

{

    int i;

    for (i = 0; i < 100; i++) {

        sm->changed = FALSE;

        SM_STEP_RUN(SUPP_PAE);//先执行SUPP_PAE状态机

        SM_STEP_RUN(KEY_RX); //再运转KEY_RX状态机

        SM_STEP_RUN(SUPP_BE); //最后运转SUPP_BE状态机

        if (eap_peer_sm_step(sm->eap)) //执行EAP_SM状态机

            sm->changed = TRUE;

        if (!sm->changed)

            break;

    }

  ......

}

其中,eap_peer_sm_step的代码如下所示:

[-->eap.c::eap_peer_sm_step]

int eap_peer_sm_step(struct eap_sm *sm)

{

    int res = 0;

    do {  //无限循环,直到EAP SM稳定后才退出

        sm->changed = FALSE;

        SM_STEP_RUN(EAP);

        if (sm->changed)

            res = 1;

    } while (sm->changed);

    return res;

}

通过上述代码可知,EAPOLEAP的状态机联动过程如下:

1EAPOL先按顺序遍历PAEKEY_RXBE状态机。

2)然后执行EAP状态机。只有EAP SM稳定后(即eap_peer_sm_step函数中的sm->changedFALSE时)才退出eap_peer_sm_step

3)如果上述四个状态机有任何一个状态机的状态不稳定(即sm->changedTRUE),则继续遍历所有状态机。

特别需要指出的是,状态机A运行时可能会修改一些条件变量从而导致状态机B发生状态切换。虽然第4章对每个状态机的状态切换图都有详细介绍,但读者很难理清楚状态机之间是如何互相影响的。在此,笔者整理了WPAS从发送EAPOL-Start包到接收EAP-Request/Identity以及回复EAP-Reponse/Identity这一过程中四个状态机的切换过程,如图6-34所示:

bubuko.com,布布扣

6-34  EAP-Request/Response Identity流程中的状态机联动示意

6-34中:

  • 最上面一行显示了PAEKEY_RXBEEAP_SM的初始状态。由于EAP-WSC不会收发EAPOL-Key帧,所以KEY_RX将不参与联动过程。
  • 图中的方框上部所示为状态机以及当前的状态,格式为状态机名_状态名,如PAE_CONNECTING等。方框下部所示为该状态机对应状态的EA处理(由于篇幅原因,图中EA仅列出了一些重要的处理逻辑)。
  • 当状态机A从一个状态切换到另一个状态时,切换过程用实箭头表示(例如第二行中,PAE_CONNECTING切换到PAE_RESTART,切换条件为“eapolEapTRUE”。当WPAS收到一个EAP帧时,该变量将在上文介绍的eapol_sm_rx_eapol函数中被设置为TRUE)。
  • 当状态机A在其EA处理中修改了某些条件变量(或者外界设置了某个条件变量)导致状态机B发生状态切换时,其切换过程用虚箭头表示。例如第二行中的PAE_RESTART状态,其EA将设置eapRestartTRUE,而该条件和portEnabled将共同促使EAP_SM进入INITILIAZE状态。
  • 第二行表示eapol_sm_step第一次循环过程中的状态机切换以处理接收到的EAP-Request/Identity包。但这一轮还不会真正处理EAP包。
  • 第三行表示eapol_sm_step的第二次循环。在这次循环过程中,EAP状态机将处理EAP-Request/Identity包。在解析该包时,发现它包含了Identity信息,所以EAP SM将进入IDENTITY状态去处理它。处理完毕后,EAP SM将构造一个EAP-Response/Identity包,并设置eapResp变量为TRUE
  • 第三行中,eapResp变量将使得BE进入RESPONSE状态,该状态的EA将调用txsuppResp发送这个EAP-Response/Identity包。

当图6-34执行完毕后,EAPOLEAP状态机将进入稳定状态,这样,eapol_sm_step得以返回。根据EAP-WSC的流程,WPAS下一步将继续接收并处理EAP包。在这以后的过程中(从M1M8):

  • PAE保持Authenticating状态不变。
  • EAPOL收到一个EAP包后,BE将从RECEIVE状态切换至REQUEST状态。EAP将根据EAP包的信息从IDLE状态转移到其他状态(首先是RECEIVED状态,在该状态中将解析EAP包的内容,根据内容以进入GET_METHODMETHOD状态以处理EAP包)。
  • EAP状态机处理完EAP包,BE将进入RESPONSE状态并发送EAP回复包。整个流程将反复执行,直到EAP-WSC流程终结。

所以,对EAP-WSC流程来说,EAPOL状态机的执行过程比较固定。而对EAP SM来说,它将根据EAP包内容的不同而转移到不同的状态。下面我们将直接进入EAP对应的状态以分析不同EAP包的处理过程。

注意,根据图4-21关于EAP SM的描述,当portEnabled值为TRUE时,应该从DISABLED状态切换至INITIALIZE状态。不过,我们在4.5.3.3.3wpa_supplicant_associate分析之三”一节中曾提到说由于force_disabled变量为TRUEEAP_SM是无法转入INITIALIZED状态的。为什么此处它却可以呢?原来。由于本例使用的key_mgmtWPA_KEY_MGMT_WPS,所以force_disabled变量将被设置为FALSE,这样EAP SM就可以转换至INITIALIZE状态了。其间的细节内容请读者参考wpa_supplicant_initiate_eapol及内部所调用的eapol_sm_notify_config函数。

 

=============================略略略===========

6.4  本章总结和参考资料说明

6.4.1  本章总结

本章对Wi-Fi Simple Configuration和其中的PIN方法进行了深入介绍。主要内容包括:

注意:WSC规范中还定义了另外一种比较常用的PBC方法。PBCPIN类似,它也会用到一个PIN码,只不过这个PIN码为“00000000”。读者可阅读参考资料[7]来了解PBC

6.4.2  参考资料说明

本章参考资料其实只有一个,即WSC规范2.0.2版。读者可在百度文库上搜索到该文档,其地址为http://wenku.baidu.com/view/aa2e8a20cfc789eb172dc83d.html

WSC应用场景介绍

[1]  WSC-2.0.21节“Introduction

WSC核心组件及接口介绍

[2]  WSC-2.0.24节“Core Architecture

Registration Protocol介绍

[3]  WSC-2.0.26.1节“In-band Setup Using a Standalone AP/Registrar

[4]  WSC-2.0.28节“Message Encoding

[5]  WSC-2.0.27节“Registration Protocol Definition

[6]  http://en.wikipedia.org/wiki/Diffie-Hellman_key_exchange

维基百科关于D-H算法的描述,读者可通过它了解D-H的相关知识。

Push Button Configuration

[7]  WSC-2.0.211节“Push Button Configuration”。

规范中,PBC的介绍只有7页。建议读者学完本章后再来看它。

 

《深入理解Android:Wi-Fi,NFC和GPS》章节连载[节选]--第六章 深入理解wi-Fi Simple Configuration,布布扣,bubuko.com

原文:http://blog.csdn.net/innost/article/details/21555225

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!