剖析Android的Smart Lock

前言

  本文的內容基於https://nelenkov.blogspot.com/2014/12/dissecting-lollipops-smart-lock.html,省略去NFC的內容。
  Android5.0已經發布有一段時間了,其大部分特性已經被介紹過,其中包含了一系列的安全增強特性,當中磁盤加密功能獲得了大部分的關注。Smart Lock(最初在2014年Google I/O大會引入)作爲安全增強特性當中一種在特定環境條件下允許鎖屏直接解鎖的特性,是最與用戶體驗直接相關的。因此,該功能被廣泛討論和記錄在博客上。然而,作爲Google Play服務內置的專屬功能,Smart Lock的實現和安全等級還未對外公開。此文會深入探究Smart Lock所在的Android Framework擴展部分,展示如何創建你自己的解鎖方法以及簡要地討論其大致實現。

信任代理(Trust agents)

  Smart Lock基於Android L的被稱爲信任代理(trust agents)的新特性。引用自相關文檔,信任代理是一個”告知系統當前設備所處環境是否被信任“的服務。信任的具體先決條件由信任代理定義。當一個信任代理認爲它可以信任當前環境,它會通過回調來告知系統,系統會決定如何去繞過設備的安全配置。當前Android的一個典型的範例是:當處於一個被信任的環境時,系統會授予用戶繞過鎖屏的能力。
  信任可以授予給不同的用戶,所以不同用戶的信任代理可以被加以區別地配置。另外,信任可以被授予一段時間,當超過這段時間以後就會重置成不信任狀態。設備的管理員可以爲信任代理設置其允許範圍內的信任時間或者禁用信任代理。

信任代理api

  信任代理是繼承自基類TrustAgentService(不在public SDK裏面,帶有@SystemApi的註解)的Android Service。基類TrustAgentService提供了諸如使能信任代理(setManagingTrust()),授予/取消信任(grant/revokeTrust()),還有一系列的回調方法,如下所示:

/frameworks/base/core/java/android/service/trust/TrustAgentService.java

public class TrustAgentService extends Service {

    public void onUnlockAttempt(boolean successful) {
    }

    public void onTrustTimeout() {
    }

    private void onError(String msg) {
        Slog.v(TAG, "Remote exception while " + msg);
    }

    public boolean onSetTrustAgentFeaturesEnabled(Bundle options) {
        return false;
    }

    public final void grantTrust(
            final CharSequence message, 
            final long durationMs, final boolean initiatedByUser) {
      //...
    }

    public final void revokeTrust() {
      //...
    }

    public final void setManagingTrust(boolean managingTrust) {
      //...
    }

    @Override
    public final IBinder onBind(Intent intent) {
        return new TrustAgentServiceWrapper();
    }
 
  
    //...
}

  如果要被系統識別到,一個信任代理需要在AndroidManifest.xml裏面聲明:1.action爲android.service.trust.TrustAgentService的intent filter;2.BIND_TRUST_AGENT的權限。如下所示。這是爲了保證可以綁定到該信任代理。在系統的AndroidManifest(frameworks/base/core/res/AndroidManifest.xml)可以看到,BIND_TRUST_AGENT權限的android:protectionLevel屬性爲"signature",意味着訪問信任代理需要系統簽名。允許跨進程調用到信任代理的Binder api也由TrustAgentService基類提供。

<manifest ... >

    <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
    <uses-permission android:name="android.permission.PROVIDE_TRUST_AGENT" />

    <application ...>
        <service android:exported="true" 
                 android:label="@string/app_name" 
                 android:name=".GhettoTrustAgent" 
                 android:permission="android.permission.BIND_TRUST_AGENT">
        <intent-filter>
            <action android:name="android.service.trust.TrustAgentService"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>

        <meta-data android:name="android.service.trust.trustagent" 
                      android:resource="@xml/ghetto_trust_agent"/>
        </service>
        ...
    </application>
</manifest>

  系統設置會掃描匹配上述intent filter的應用,檢測它們是否需要用< uses-permission>指定了PROVIDE_TRUST_AGENT權限(定義在名爲"android"的包中:frameworks/base/core/res/AndroidManifest.xml),如果所有條件滿足就將其顯示在信任代理列表界面(Settings->Security->Trust agents)中。此外,如果manifest文件裏面包含的< meta-data>標籤指向一個定義了setting activity的XML資源(如下所示),一個打開對應的setting activity的菜單入口會被添加到信任代理界面中。

<trust-agent xmlns:android="http://schemas.android.com/apk/res/android"
        android:title="Ghetto Unlock"
        android:summary="A bunch of unlock triggers"
        android:settingsActivity=".GhettoTrustAgentSettings" />

  下圖是信任代理列表界面。
在這裏插入圖片描述

  信任代理默認不被激活(除非是system.img要求是激活的),但會在用戶打開上圖中的開關時激活。激活的信任代理由TrustManagerService掌管。TrustManagerService保存了很多和信任相關的事件。你可以使用以下命令dump出信任事件,獲得當前的信任狀態。

$ adb shell dumpsys trust
Trust manager state:
 User "Owner" (id=0, flags=0x13) (current): trusted=0, trustManaged=1
   Enabled agents:
    org.nick.ghettounlock/.GhettoTrustAgent
     bound=1, connected=1, managingTrust=1, trusted=0
   Events:
    #0  12-24 10:42:01.915 TrustTimeout: agent=GhettoTrustAgent
    #1  12-24 10:42:01.915 TrustTimeout: agent=GhettoTrustAgent
    #2  12-24 10:42:01.915 TrustTimeout: agent=GhettoTrustAgent
    ...

授予信任

  一旦信任代理被激活,授予信任會被特定的可觀測的環境事件或者用戶認證觸發。一個經常用到的但是不是特別安全的例子:連接到"Home" wifi時觸發解鎖。這個功能可以通過響應android.net.wifi.STATE_CHANGE的廣播來實現(見sample app。一旦偵測到連接到一個信任的SSID,廣播接收器只需調用grantTrust()來進行授權。這可以通過多種方法來實現,如果信任代理和廣播接收器在同一個包裏面,一種比較直接的方式是使用LocalBroadcastManager(support庫包含),如下所示。

static void sendGrantTrust(Context context,
                           String message, 
                           long durationMs, 
                           boolean initiatedByUser) {
    Intent intent = new Intent(ACTION_GRANT_TRUST);
    intent.putExtra(EXTRA_MESSAGE, message);
    intent.putExtra(EXTRA_DURATION, durationMs);
    intent.putExtra(EXTRA_INITIATED_BY_USER, initiatedByUser);
    LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}


// in the receiver
@Override
public void onReceive(Context context, Intent intent) {
    if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(intent.getAction())) {
        WifiInfo wifiInfo = (WifiInfo) intent
                        .getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
       
        // ...
        if (secureSsid.equals(wifiInfo.getSSID())) {
            GhettoTrustAgent.sendGrantTrust(context, "GhettoTrustAgent::WiFi",
                                            TRUST_DURATION_5MINS, false);
        }
    }
}

  grantTrust()會調用鎖屏組件安裝的ITrustAgentServiceCallback 回調並設置一個flag。如果信任時間已過,用戶必須重新輸入圖案或PIN碼或密碼來解鎖屏幕。當前的解鎖狀態會以一個掛鎖圖標的形式呈現在鎖屏界面底部:當解鎖時,表示當前的環境是可信任的。即使當前環境是可信任的,用戶也可以點擊掛鎖圖標來對設備進行重新加鎖。

Smart Lock

  "Smart Lock"是GoogleTrustAgent組件的用戶稱呼,包含在GMS包中,見下面dump出來的信息:

$ adb shell dumpsys trust
Trust manager state:
 User "Owner" (id=0, flags=0x13) (current): trusted=1, trustManaged=1
   Enabled agents:
    com.google.android.gms/.auth.trustagent.GoogleTrustAgent
     bound=1, connected=1, managingTrust=1, trusted=1
      message=""

  信任代理提供了幾種解鎖觸發方式:可信設備,可信地點和可信面孔。可信面孔是以往版本的臉部解鎖的重新包裝。它使用了相同的圖像識別技術,但是更實用,因爲當可信面孔啓用時,鎖屏會持續掃描以得到一個匹配的面孔而不是要求用戶在拍照和處理圖像時保持靜止。就像可信面孔啓動的界面提示一樣,這種方式提供的安全等級是相當低的。可信地點是基於地理圍籬科技實現的,這種技術在Google Play服務中已經實現有一段時間。可信地點使用與用戶的Google賬號相關的"Home"和“Work"地點來使得啓動更加便捷,並且允許註冊自定義的基於當前位置的地點或者Google Maps中任意可選的座標。就像幫助窗口提到的,可信地點的精度無法保證,信任的地點範圍會達到100米。實際上,設備在超出範圍一段時間之內仍能保持解鎖狀態。
  可信設備目前包括兩種設備:藍牙和NFC。藍牙選項允許設備在配對設備在一定範圍內時保持解鎖狀態。這種特性依靠藍牙內置的安全特性來實現,藍牙選項的安全性依靠其匹配的設備。更新的設備例如Android Wear和Pebble watch,支持Secure Simple Pairing配對方式(4級安全等級),使用ECDH算法來產生一個共享鏈接密鑰。在配對過程中,這些設備會顯示一個基於雙方設備的公鑰的哈希值生成的6位數來提供設備認證功能,避免MITM攻擊(這個特性被稱爲數字比較)。然而,老舊設備例如Meta Watch,藍牙耳機和其他一些設備也支持可信設備功能。這些前代產品僅僅支持標準匹配,這些設備通過設備物理地址和4位數PIN碼來產生認證密鑰,然而這個PIN碼通常是固定的,且被設置成一些簡單易記的數值,例如’0000‘和’1234‘。這些設備容易被冒充。
  Google的Smart Lock的實現裏要求與信任設備保持持續的連接,一旦連接斷掉,信任就會被撤銷(更新:在Android5.1以前,一個信任的的連接能夠不使用密鑰來建立)。然而,就和引導界面所提到的,藍牙範圍是可變的而且能達到100米。因此,當連接到可信腕錶設備時讓設備保持解鎖的使用場景看起來很靠譜,實際上,當可信的藍牙設備在另一個房間時,Android設備仍能保持解鎖狀態。
在這裏插入圖片描述

總結

  Android 5.0(Lollipop)基於信任代理引入了全新的trust framework,用來告知系統何時設備處於可信任的環境中。因爲鎖屏監聽信任事件,所以會根據當前用戶的信任事件來改變其行爲。配置信任代理的方式使得增強或代替傳統的圖案/PIN碼/密碼的用戶認證方式變得更加容易。信任代理功能目前僅僅對系統應用開放。Google Play服務在Smart Lock提供了幾種信任觸發條件。雖然Smart Lock大大提高了設備易用性,但是目前Smart Lock的判斷方法沒有一種是精確或者安全的,所以要小心使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章