DPP / Wi-Fi Easy Connect 簡介
日常生活中,我們經常都需要連接不同的 Wi-Fi 熱點。例如:當我們去到咖啡店的時候,通常牆身都會寫上了 Wi-Fi 的 SSID 和密碼。或者當去到朋友家的時候,我們也會問朋友拿 Wi-Fi 的密碼。不過,以這種方法連接 Wi-Fi,其實會帶來兩個潛在的資安風險:「主動攻擊」和「被動攻擊」。
「主動攻擊」是指,有一些黑客,他們會主動去製造一些假的 Wi-Fi AP 基站:只要它們發出同樣的 SSID,設上同樣的密碼,用家就有可能會不小心連上了這些假 AP。只要訊號夠強,速度夠快,大部分用家根本不會發現。這樣,黑客就能發動中間人攻擊 (man-in-the-middle attacks),去盜取用家所有的訊息。
「被動攻擊」則指,黑客們只負責竊聽 (eavesdrop) 在大氣電波中的數據,並不主動發動攻擊。由於密碼都寫在牆上了,所以只要基站 (AP) 與使用者 (STA) 雙方,都沒有用上足夠安全的加密協議(例如只使用了 WEP / WPA / WPA2)的話,黑客就可以輕易將內容解密。
DPP / Wi-Fi Easy Connect 協議的出現,正正是為了解決以上的情況而設計的。簡單來說,在主動攻擊方面,DPP 透過公私鑰的交換,確保用戶只會連到真正的 AP。而在被動攻擊方面,DPP 使用了迪菲-赫爾曼密鑰交換 (Elliptic Curve Diffie-Hellman Key Exchange) 的方法,建立出獨一無二的 session key。所以,即使竊聽者擁有密碼,他們也沒辦法輕易推斷出 session key,繼而也無法解密訊息。
這篇文章,我只會簡介 DPP 的不同步驟 (steps) 、角色 (roles) 和在 hostap 的實作。關於 Public Private Key Infrastructure (PKI)、Diffie-Hellman 的原理和每個步驟的細節,之後會再寫另一篇解釋。
DPP 五大步驟
簡單來說,如果只考慮 AP 與 STA 之間的協議,DPP 有以下五大步驟:
- Bootstrapping (起步):這個步驟是 DPP 的第一步。它指使用頻外驗證 (Out-of-band Authentication) 的方法去交換公鑰。例如將公鑰印成 QR code 貼在牆上、印在機身,或者使用藍芽或 NFC 這類近距離的方法。
- DPP Authentication(DPP 驗證):在 bootstrapping 期間成功交換的公鑰,將會用作 HMAC 的參數,繼而產生三條不同的 session keys (k1, k2 以及 ke)。這個步驟主要用作確保雙方均在開機的狀態(又稱為 Aliveness),而且產生出來的 ke 是獨一無二的。
- DPP Configuration(DPP 設定佈置):當 authentication 產生了 ke 後,configuration 會用這個 ke (配以 AES-SIV)來加密 Wi-Fi AP 的登入憑證 (credentials / configuration object)。例如,它會包含 SSID, WPA3/WPA2 密碼,或者是 DPP Connector 公私鑰。(如果是 DPP Connector 的話,Connector 入面還包含了 groupId 和 netRole 這些資訊,而且該 connector 會以 ECDSA 簽名,所以任何接收到 connector 的人,都不能擅自改動 connector 的內容。)
- DPP Network Introduction / Peer Discovery(DPP 設備探索):這個步驟只適用於有收到 DPP Connector 的情況(如果是 WPA2/3,它就會離開 DPP,走傳統的連線方法)。簡單而言,不同裝置之間會在這步交換 connector,去查核對方的 groupId 和 netRole。如果對方的 netRole 正確,就會繼續產生 Pairwise Master Key (PMK)。例如,如果 AP 擁有一個 groupId="Group1" 和 netRole="ap" 的 connector,而 STA 則擁有一個 groupId="Group1" 和 netRole="sta" 的 connector 的話,因為它有相同的 groupId,而且一個是 ap,另一個是 sta,所以雙方就會同意繼續連線,並且用 connector 中的 netaccesskey 進行 ECDH 及 HKDF,產生 PMK。
- DPP Network Access / Association(DPP 網絡接入):最後一步,就是使用在 peer discovery 中產生的 PMK 接入 Wi-Fi AP。這個步驟大致上跟 WPA2 的 PSK 相似,只是把 PSK 換成了 PMK。所以,STA 會以 Open 認證方式連上 AP,再跑 EAPOL (4-way handshake),從而由 PMK 產生一條新的 PTK。在產生過程中,使用者亦可在 DPP KDE 中表示對 PFS (Perfect Forward Secrecy) 的支援,它就會在接入的過程中,使用 AP 在 RSN IE 中廣播的 Z 公鑰,以加強 PTK 的獨特性。
DPP 的四大角色
在官方的文檔中,有四個角色 (Initiator / Responder / Configurator/ Enrollee) 經常出現混淆。
但其實,分類方法十分簡單:
DPP Authentication 中有兩個角色:
- Initiator(發起者):它接收由 Responder 發出的 DPP URI,然後發出 Authentication Request。 (如果啟用了雙向驗證的話,則兩者互換 DPP URI)
- Responder(回應者):它接收 Authentication Request,並以 Authentication Response 回應 Initiator 的請求。
DPP Configuration 中有兩個角色:
- Configurator(佈局者):它儲存了所有憑證 (credentials) 相關的資訊,也會在別人發出 Configuration Request 時,以 Configuration Response 回應它的請求。它也有一條 Certificate Signing Key (又稱 csign key), 用作簽發 DPP connector 之用。
- Enrollee(登記者):所有希望接收憑證 (credentials) 的人都是 Enrollee。它們會發出 Configuration Request,等待 Configurator 的回應。
這四個角色,可以隨著不同的情況完全自由配搭,例如:
- AP (Initiator + Configurator) 配搭 STA (Responder + Enrollee)
- AP 通過掃瞄 STA 的 QR code,令 STA 可以連上 AP
- 這種情況,AP 是路由器的 App,STA 則是 IoT 設備
- STA (Initiator + Configurator) 配搭 AP (Responder + Enrollee)
- STA 掃瞄 AP 的 QR code,然後設置路由器的 WPA2/3 密碼
- 比較少見,但理論上可行
- STA (Initiator + Configurator) 配搭 STA (Responder + Enrollee)
- 兩部手機之間互相分享 WPA2/WPA3 密碼
- Android STA 已部分支援這個功能 (Initiator + Configurator)
- AP (Responder + Configurator) 配搭 STA (Initiator + Enrollee)
- AP 產生一個 QR code 貼在牆上,其他 STA 一掃就能連上。
- AP 是路由器,STA 是手機
- STA (Responder + Configurator) 配搭 STA (Initiator + Enrollee)
- 兩部手機之間互相分享 WPA2/WPA3 密碼
- Android STA 已部分支援這個功能 (Initiator + Enrollee)
反正就是,只要你想到的,就可以做到,協議中並沒有限制角色配搭的可能性。
在 HostAP 中實作
現時,hostap 2.9 只支援大部分的 DPP 1.0,以及少部分的 DPP 2.0。
而在最新的 commit 中(截稿前是這個),大部分 DPP 2.0 的實作已經做好。
以下的 hostap 指令例子,是以 AP (Initiator + Configurator) + STA (Responder + Enrollee) 為基礎的。你也可以把它想像成這個 use case :
- hostapd 是路由器
- hostapd_cli 是路由器的手機界面
- wpa_supplicant 和 wpa_cli 是沒有按鈕,只顯示著 QR code 畫面的 IoT 裝置
Step 1: STA - 放以下的 config (wpa_dpp.conf):
ctrl_interface=DIR=/var/run/wpa_supplicant
ctrl_interface_group=0
update_config=1
pmf=2
dpp_config_processing=2
Step 2. STA - 跑以下的命令,開啟 wpa_supplicant:
./wpa_supplicant -d -Dnl80211 -iwlp1s0 -cwpa_dpp.conf
Step 3. STA - 跑以下的命令,產生一條新的 DPP URI QR code,然後等待連線:
./wpa_cli dpp_bootstrap_gen type=qrcode chan=81/1
dpp_bootstrap_get_uri 1
dpp_listen 2412
將產生的 QR code 拷貝下來,在 Step 6 會用到。
Step 4. AP - 放以下的 config (hostapd_dpp.conf):
interface=wlp0s20f3
driver=nl80211
ctrl_interface=/var/run/hostapd
ssid=test
channel=1
wpa=2
wpa_key_mgmt=DPP
ieee80211w=1
wpa_pairwise=CCMP
rsn_pairwise=CCMP
Step 5. AP - 跑以下的命令,開啟 hostapd:
./hostapd -d hostapd_dpp.conf
Step 6. AP - 打開 hostapd_cli,並貼上剛拷貝的 DPP URI 到以下的命令中
./hostapd_cli
dpp_qr_code <YOUR COPIED DPP URI>
Step 7. AP - 在 hostpad 中加一個 configurator。這個 configurator 將會用來簽發所有裝置(包括 ap 自己)的 DPP connectors :
dpp_configurator_add
Step 8. AP - 用 configurator 為 ap 自己,簽發一個 connector。在 Peer Discovery 中,每一個裝置都是用 connector 去交換身分資料,所以,ap 自己也需要一個 connector:
dpp_configurator_sign conf=ap-dpp ssid=74657374 configurator=1
Step 9. AP - 把剛剛 configurator 產生的 connector 套用到 ap 本身身上。這樣,當有 peer discovery request 的時候,ap 就可以把自己的 connector 傳出去,而且也懂得用套用上的 csign public key 驗證對方的 connector:
set dpp_connector <CONNECTOR VALUE IN TERMINAL>
set dpp_csign <CSIGN VALUE IN TERMINAL>
set dpp_netaccesskey <NETACCESSKEY VALUE IN CONSOLE>
注意這裏的 connector 是已經簽好的 base64 字串,裏面包含了 groupId, netRole, netaccesskey 的public key 和一個 ECDSA 簽名。這個 csign key 則是 public key (csign key 的 private key 是藏在 configurator 裏面的)。而最後,這個 netaccesskey 則是 private key,用作給 ap 在 peer discovery 時產生 PMK 之用。
Step 10. AP - 因為 AP 是 initiator 及 configurator,所以要跑以下命令,發起 DPP authentication request。這個命令也要求 configurator 在 configuration response 期間,產生一個 netrole=sta, ssid=test 的 dpp connector 回傳給對方 :
dpp_auth_init peer=1 conf=sta-dpp ssid=74657374 configurator=1
小結
DPP (Device Provisioning Protocol,又名 Wi-Fi Easy Connect)是近年來比較新的 Wi-Fi 驗證方法。雖然它仍然需要 out-of-band 的方法去做第一步,而且步驟繁瑣,但至少也算是提供了一個可行的做法。
它的設計邏輯,其實跟 USB Type C 也有點類似:它提供了同一樣的接口,讓兩個裝置至少溝通得上,但實際支援與否,則要看它在交換的過程中,對方的 role 與自己是否配搭。
作為 protocol designer,我認為 DPP 的 signalling messages 實在有點多,而且對 WPA2 的 backward compatibility 可能會令所有事情功虧一簣。但另一方面,正正因為它把步驟都拆分得很細,它也可以在耗用系統資源較少的情況下,及早辨認出 DoS flooding 的封包。這一點,對於未來「萬物皆互聯」的世界,似乎對系統穩定性也有幫助。
但是,如果文檔附有 formal verification 的話,我相信說服力應該會再大一點。
---
引用
[1] - Wi-Fi Easy Connect Spec 2.0 - https://www.wi-fi.org/download.php?file=/sites/default/files/private/Wi-Fi_Easy_Connect_Specification_v2.0.pdf
[2] - AOSP Wi-Fi Easy Connect - https://source.android.com/devices/tech/connect/wifi-easy-connect