跟一下wpa_supplicant(3-2) connect AP

接前面(3-1)繼續:安全

 

5. 接分支4.
authenticate response 來了
和前面同樣:
wpa_driver_nl80211_event_receive到
=> process_event
   收到 NL80211_CMD_AUTHENTICATE=37
   ==> mlme_event (37)
       ===> mlme_event_auth
            authenticate response 管理幀中的AP mac 是咱們感興趣的,
     收了它,放wpa_driver_nl80211_data 的auth_bssid
            並放到wpa_event_data->auth_info->peer
     ====> wpa_supplicant_event(drv->ctx, EVENT_AUTH, &event);
           Event 11 received on interface wlan0 被扔出來
          =====> sme_event_auth(wpa_s, data);
                       緊接着
         D/wpa_supplicant( 2129): SME: Authentication response:
                        peer=00:1f:33:b9:5d:e0 auth_type=0 status_code=0
                       被扔出來
                       ======> eloop_cancel_timeout(sme_auth_timer,
                     wpa_s, NULL);
                               取消auth 失敗的警惕,能夠進城了
                       ======> sme_associate(wpa_s, ssid->mode,
                  data->auth.peer, data->auth.auth_type);
    啓動關聯
                               =======>wpa_supplicant_set_state(wpa_s,
                    WPA_ASSOCIATING);
                               ========> wpa_s->new_connection = 1;
                               ========> wpa_drv_set_operstate(wpa_s, 0);
                   /* 設置到IF_OPER_DORMANT */
                               ========> wpa_s->wpa_state = state;
                               ========> wpas_notify_state_changed(wpa_s,
             wpa_s->wpa_state, old_state);
        若是 oldstate  不一樣狀況下執行
                               =======> 設置參數等,ie
                               =======> wpa_drv_associate(wpa_s, &params)
                                wpa_driver_nl80211_associate  driver interface
           經過netlink 給dirver 發assoc request
                                wpa_printf(MSG_DEBUG, "nl80211:
       Association request send "  "successfully");
                                發完了應該,別忘警惕下:
                       =======> eloop_register_timeout(SME_ASSOC_TIMEOUT,
                                 0, sme_assoc_timer, wpa_s,  NULL);
                                 /* 關聯超時失敗處理*/
       
                             接下來到分支6.網絡

6. 接分支5.
38 event 來了!
wpa_driver_nl80211_event_receive到
=> process_event
   ==> mlme_event (38= NL80211_CMD_ASSOCIATE)
       asscoicate response 來了
      ===> mlme_event_assoc(drv, nla_data(frame),
             nla_len(frame));
      這裏的 frame 應該就是關聯響應幀
             去讀下rp frame state 判斷response爲成功
          ====> drv->associated = 1;
          ====> 得到resp 中的IE們 到 event.assoc_info.resp_ies
          ====> event.assoc_info.freq = drv->assoc_freq;
        關聯時的頻率放到 struct assoc_info
         有了IE,就象口袋有錢,能夠來事了,EVENT_ASSOC發出去
          ====> wpa_supplicant_event(drv->ctx, EVENT_ASSOC,&event);
               =====> wpa_supplicant_event_assoc(wpa_s, data);
                     ======> wpa_supplicant_event_associnfo
                            獲取AP 的assoc info!
       就是挖掘前面說的已經存到event.assoc_info的resp ie
       其中若是挖到PMKID,是要注意
       去call wpa_find_assoc_pmkid
       幹什麼? 若是忘記了,到第1篇搜索:
       '成對主蜜鑰安全關聯'字樣,我就不講了函數

                     ======> wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED);
                             State: ASSOCIATING -> ASSOCIATED
                     ======> wpa_clear_keys (clear driver config key)
                     ======> wpa_supplicant_select_config
              咱們設置爲AP_SCAN =1(讓wpa_supplciant選擇AP)
       因此它什麼也不作,return
                     ======> wpa_sm_notify_assoc(wpa_s->wpa, bssid);
                            WPA state machine 的rx_replay_counter_set 清0,
       的renew_snonce 置1
       比較下是不是在preauth的ap 的mac,是的話就deinit它
       最後清下wap state machine 的 old PTK
       這麼作是由於人家IEEE 802.11協議8.4.10部分說了
                            Delete PTK SA on (re)association if this is not
          part of a Fast BSS Transition.
                           
                            PTK 有兩種格式,TKIP,和CCMPoop

                     ======> eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
                     ======>eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
       ======> if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
                                   ft_completed)
                          eapol_sm_notify_eap_success(wpa_s->eapol,
                                FALSE);  
                      到這裏PAE還沒變化,下面就要變了
                     ======> eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
                            portEnabled=1
       PAE狀態要發生變化了,從disconnect 變到connecting
                            這個disconnect是在 eapol_sm_init,開始設置的
       以後一直保持該狀態
       EAP狀態一直爲disable,由於咱們是WPA-psk,因此
       沒有EAP,他就一直處於disablethis

                     ======> /* Timeout for receiving the first
                  EAPOL packet */
                       wpa_supplicant_req_auth_timeout(wpa_s, 10, 0);
         /* 10  秒後沒收到第1個 eapol packet 後 ,
         就處理auth 失敗 */
                     ======> wpa_supplicant_cancel_sched_scan(wpa_s);
       /* 要作正事了, 就先停sched scan ,scan  */
                  wpa_supplicant_cancel_scan(wpa_s);加密

                     ======> wpa_supplicant_event_assoc中
                接下來的部分不會執行到spa


到這裏已經關聯已經完成,在AP 發來EAPOL frame 前,咱們會收到
NL80211_CMD_CONNECT 通知,根據cmd註釋,能夠了解該命令是在不分開進行認證
和關聯的狀況下,來請求鏈接到一個指點網絡的,鏈接完成會收到NL80211_CMD_CONNECT
的response,目前的driver capa裏設置了WPA_DRIVER_FLAGS_SME,表示driver 支持
auth 和associate 分開的命令,因此能收到NL80211_CMD_CONNECT,但不處理
爲何呢? 註釋裏已經寫了,爲了不2次報告關聯事件,引發核心代碼混亂
/** Avoid reporting two association events that would confuse
 * the core code.
 */.net

                   進入7. 繼續unix

7. 前面6.中完成asscicate 後,講過就會等待EAPOL FRAME到來
  在wpa init 中 wpa_supplicant_driver_init 會註冊 l2 rx callback
wpa_s->l2 = l2_packet_init(wpa_s->ifname,
     wpa_drv_get_mac_addr(wpa_s),
     ETH_P_EAPOL,
     wpa_supplicant_rx_eapol, wpa_s, 0);code

能夠看出收到l2 packet 後call back wpa_supplicant_rx_eapol,就從它開始
=> wpa_supplicant_rx_eapol:
   ==> wpa_supplicant_req_auth_timeout(wpa_s,
              (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
       wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA
               || wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ? 70 : 10, 0);
        和前面associate最後設置的10s timeout 同樣,這裏只是收到
 第1個,reset 下一次認證超時爲10s

   ==> wpa_s->eapol_received++;  是第1次,eapol_received++ 後等於1
   ==> wpa_drv_poll(wpa_s);
   ==> if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
          ===> wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
              該函數處理收到的 EAPOL frame
              分析可得:
                * type =2 時 EAPOL-Key
  * key_info =0x8a
     (ver=2 keyidx=0 rsvd=0 Pairwise Ack)
  * key length =16, key data lenght 22
key_info 各bit 所表明的內容在:
wpa_comm.h中定義以下:


點擊(此處)摺疊或打開

  1. /* IEEE 802.11, 8.5.2 EAPOL-Key frames */

  2. #define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2)))

  3. #define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0)

  4. #define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1)

  5. #define WPA_KEY_INFO_TYPE_AES_128_CMAC 3

  6. #define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key */

  7. /* bit4..5 is used in WPA, but is reserved in IEEE 802.11i/RSN */

  8. #define WPA_KEY_INFO_KEY_INDEX_MASK (BIT(4) | BIT(5))

  9. #define WPA_KEY_INFO_KEY_INDEX_SHIFT 4

  10. #define WPA_KEY_INFO_INSTALL BIT(6) /* pairwise */

  11. #define WPA_KEY_INFO_TXRX BIT(6) /* group */

  12. #define WPA_KEY_INFO_ACK BIT(7)

  13. #define WPA_KEY_INFO_MIC BIT(8)

  14. #define WPA_KEY_INFO_SECURE BIT(9)

  15. #define WPA_KEY_INFO_ERROR BIT(10)

  16. #define WPA_KEY_INFO_REQUEST BIT(11)

  17. #define WPA_KEY_INFO_ENCR_KEY_DATA BIT(12) /* IEEE 802.11i/RSN only */

  18. #define WPA_KEY_INFO_SMK_MESSAGE BIT(13)



第1個發過來的eapol frame 表示4次握手的第1次握手已經開始了!!!

   ==> 接下來就是部分4 way handle 的代碼,直接貼上:


點擊(此處)摺疊或打開

  1. if (key_info & WPA_KEY_INFO_KEY_TYPE) {

  2.      /* 走到這裏, WPA_KEY_INFO_KEY_TYPE ,pairwise ,or group key !!!*/

  3.    if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {

  4.  wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,

  5.  "WPA: Ignored EAPOL-Key (Pairwise) with "

  6.  "non-zero key index");

  7.  goto out;

  8.    }

  9.    if (peerkey) { /* 若是4way 的第1次沒有peerkey */

  10.       /* PeerKey 4-Way Handshake */

  11.   peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver);

  12.    } else if (key_info & WPA_KEY_INFO_MIC) {

  13.      /* 3/4 4-Way Handshake */

  14.      wpa_supplicant_process_3_of_4(sm, key, ver);

  15.    } else {

  16.        /* 1/4 4-Way Handshake */

  17.  wpa_supplicant_process_1_of_4(sm, src_addr, key, ver);

  18.    }

  19. } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {

  20.      /* PeerKey SMK Handshake */

  21.      peerkey_rx_eapol_smk(sm, src_addr, key, extra_len, key_info,ver);

  22. } else {

  23.  if (key_info & WPA_KEY_INFO_MIC) {

  24.  /* 1/2 Group Key Handshake */

  25.  wpa_supplicant_process_1_of_2(sm, src_addr, key, extra_len, ver);

  26.   } else {

  27.          wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,

  28.         "WPA: EAPOL-Key (Group) without Mic bit - "

  29.   "dropped");

  30.  }

  31. }


 

wpa_supplicant_process_1_of_4(sm, src_addr, key, ver);
wpa_supplicant_process_3_of_4(sm, key, ver);
是咱們關心的

爲何沒有0_of_4, 2_of_4? 不是沒有,4次握手的第1,3次都在AP端處理
咱們無論了,因此目前階段,直接跑到1_fo_4,處理以下
 
       ===> wpa_supplicant_process_1_of_4(sm, src_addr, key,  ver);
            ====> wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
                  wap state 變化了 , ASSOCIATED -> 4WAY_HANDSHAKE
            ====> wpa_supplicant_parse_ies(_buf, len, &ie);
                  將buf 內容解析到 struct wpa_eapol_ie_parse
                  包括咱們下面要用的pmkid
            ====> wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
       若是pmksa cashe 不空,
       先從PMKSA cache中根據傳來的ie.pmkid 去匹配
       而後得到PMK,它是計算 PTK必須的,但如今cur_pmksa
       爲空,那如何得到pmk ,其實上面已經設置了,
       在wpa_supplicant_associate 的
       最後 wpa_sm_set_pmk 將預共享密鑰PSK,copy到
        struct wpa_sm->pmk
                   
            ====> ptk = &sm->tptk;
            ====> wpa_derive_ptk(sm, src_addr, key, ptk);
                  計算方法:
               wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
                  sm->own_addr, sm->bssid, sm->snonce, key->key_nonce,
                  (u8 *) ptk, ptk_len,
                  wpa_key_mgmt_sha256(sm->key_mgmt));
                  公式:
                  * PTK = PRF-X(PMK, "Pairwise key expansion",
                  *             Min(AA, SA) || Max(AA, SA) ||
                  *             Min(ANonce, SNonce) || Max(ANonce, SNonce))

            ====> wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver,
         sm->snonce, sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, ptk)
                  =====> wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
            NULL, sizeof(*reply) + wpa_ie_len, &rlen,
     (void *) &reply);
                       os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
                       wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, 
             rbuf, rlen, reply->key_mic);
                      /* 發出去,而後等下次 wpa_supplicant_rx_eapol*/

                   接下來到8.

 

8.
l2 packet 又來了
=> wpa_supplicant_rx_eapol:
   ==> wpa_drv_poll(wpa_s);
   ==> if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
        wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
        該函數處理收到的 EAPOL frame
        分析可得:
        * type =2 時 EAPOL-Key
 * key_info =0x13ca
    (ver=2 keyidx=0 rsvd=0 Pairwise Install Ack MIC Secure Encr)
 * key length =16, key data lenght 80
   ==>  else if (key_info & WPA_KEY_INFO_MIC) {
         /*wpa_commom.h #define WPA_KEY_INFO_MIC BIT(8)*/
  /* 3/4 4-Way Handshake */
   ==>  wpa_supplicant_process_3_of_4(sm, key, ver);
       其中key 就是 EAPOL-KEY 內容
struct wpa_eapol_key {   /* EAPOL-KEY 結構!!! */
 u8 type;
 /* Note: key_info, key_length, and key_data_length are unaligned */
 u8 key_info[2]; /* big endian */
 u8 key_length[2]; /* big endian */
 u8 replay_counter[WPA_REPLAY_COUNTER_LEN];
 u8 key_nonce[WPA_NONCE_LEN];
 u8 key_iv[16];
 u8 key_rsc[WPA_KEY_RSC_LEN];
 u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */
 u8 key_mic[16];
 u8 key_data_length[2]; /* big endian */
 /* followed by key_data_length bytes of key_data */
} STRUCT_PACKED;
        下面對eapol key data 部分進行處理,將得到的ie,放到
 struct wpa_eapol_ie_parse
        ===> pos = (const u8 *) (key + 1);  eapol key 後就是ie
             len = WPA_GET_BE16(key->key_data_length);   
             wpa_supplicant_parse_ies(pos, len, &ie);
                    
        ===> wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
                      NULL, 0, &sm->ptk)
             ====> wpa_sm_alloc_eapol ,init epaol packet
                   =====> wpa_eapol_key_send(sm, ptk->kck, ver, dst,
               ETH_P_EAPOL,  rbuf, rlen, reply->key_mic);
        一個ACK ,沒有什麼實質內容,也不加密
        ===> wpa_supplicant_install_ptk (struct wpa_sm *sm,
                   const struct wpa_eapol_key *key)
              ====> 設置driver key !!! wpa_sm_set_key
                    wpa_driver_nl80211_set_key  (nl80211 driver)
                    wap_supplicant 的 終極目標,終於看到了!
      PTK 安裝好了,稍侯片刻,立刻結束

        ===> eapol_sm_notify_portValid(sm->eapol, TRUE);
               前面associate 成功後 PAE 處於 CONNECTING
               到這裏 portValid = TRUE, 但PAE 狀態沒發生變化

        ===> wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
             WPA State 從 4WAY_HANDSHAKE -> GROUP_HANDSHAKE

        ===> wpa_supplicant_pairwise_gtk(sm, key, ie.gtk,ie.gtk_len,
                                    key_info)
             從代碼中看加密的GTK 3/4 way  中的IE部分就發來了!!!
             wpa_supplicant_check_group_cipher
      用雙方都已知道的PTK 的 EPAOL KEK 加的密 )如今解開來
             ====> wpa_supplicant_install_gtk(sm, &gd, key->key_rsc)
            安裝組密碼
             ====> wpa_supplicant_key_neg_complete   key 協商完成
                   =====> wpa_sm_cancel_auth_timeout(sm);
            將前面設置的認證超時處理取消
                   =====> wpa_sm_set_state(sm, WPA_COMPLETED);
             wpa state 從 GROUP_HANDSHAKE -> COMPLETED
                   =====> if (secure) {
                            ......
                     eapol_sm_notify_portValid(sm->eapol, TRUE);
                     eapol_sm_notify_eap_success(sm->eapol, TRUE);
       PAE 進入AUTHENTICATING
       BE  進入success
       EAP 返回diable
       PAE 最終進入AUTHENTICATED
         而後eapol_sm_set_port_authorized
                              而後wpa_supplicant_port_cb
         而後wpa_drv_set_supp_port
         設置driver NL80211_STA_FLAG_AUTHORIZED
到此爲止,認證完成

整個過程的WPA State變化以下:
(wpa_supplicant)
DISCONNECTED    -> SCANNING
SCANNING        -> AUTHENTICATING      (802.11身份認證 )
AUTHENTICATING  -> ASSOCIATING
SCANNING        -> ASSOCIATING
ASSOCIATING     -> ASSOCIATED    
     
ASSOCIATED      -> 4WAY_HANDSHAKE
4WAY_HANDSHAKE  -> 4WAY_HANDSHAKE
4WAY_HANDSHAKE  -> GROUP_HANDSHAKE
GROUP_HANDSHAKE -> COMPLETED

PAE supplicant 端狀態圖

 

 

結束

相關文章
相關標籤/搜索