code

2017年12月6日 星期三

Keychain & TouchID 整合

Keychain

keychain是一個database,每個key-value pairs稱為一個keychain item,所有的values都加密過,特別適合用來儲藏小size的user secrets。

Keychain需要link ios Security.framework,我們的application透過SecItem API來存取keychain items:



app process透過SecItem API把我們的request丟給另一個process "securityd",這算是一個中間人,因為他雖然可以query Keychain database,但是並沒有decrypt keychain value的能力,所以"securityd"會再把這個encrypted value丟到Apple A7+ chip上面的硬體security code processor稱為 Secure enclave,由此module決定是否要decrypt。

Keychain安全性

1. 被使用者iphone密碼保護
2. 被使用者iphone 出廠設定的unique device secret保護
3. keychain只有當使用者解鎖之後才能access
4. access control (只有儲存data的app能access自己的data)

總之Keychain是Apple保護某個on disk的secrets的功能,我們可以確信此protection是安全的,但是我們application的責任就是:不能把解密過後的secrets長期放到memory中(e.g. global/static variables),或是透過網路傳送


SecItem APIs

SecItem是C API:






Data protection classes

Keychain裡面的item能否被access,藉由設定以下幾種可能的protection profiles給kSecAttrAccessible attribute:



包括以下幾種(詳見api document說明):



但是以上幾種不能確定使用者到底有沒有設定device passcode,除非使用以下:


上面這個protection class 是說keychain只有當user authenticate之後才能access,而且當user lock device之後就不能access。當passcode被移除的話,在Secure enclave上的passcode secret就會被移除,所以再也無法解密被保護的items。


Keychain Access Control List (ACL)

每當app要access被ACL和touch id保護的keychain item的時候,以下這個畫面就會跳出來:



輸入device passcode標準介面:



ACL定義:
1. authentication,藉由policy control:



2. item accessibility



Touch ID Authentication

touch ID可以用來當作authenticate,用來驗證可否存取keychain裡面的item,安全性來自Secure enclave,所有的touch id data都存放在secure enclave中,而且所有的touch id operations都在secure enclave中完成,即便OS kernel被compromised也不影響其安全性,因為是一個sandbox。

Secure enclave如果發現touch id數次驗證未過的話,就會強制只能透過device passcode authenticate,重新輸入device passcode之後就能恢復使用touch id authentication。

注意keychain key operations也是在secure enclave中完成,所以跟touch id搭配是非常適合的。

使用ACL來進行touch id authentication是由LocalAuthentication framework提供API來讓application使用:




Code Example

儲存secrets: 原本沒有ACL control的keychain storage如下


如果我們加上ACL control:



讀取secrets



SecItemCopyMatching會啟動LocalAuthentication 功能,所以系統的指紋辨試或是passcode輸入畫面就會出現。不過為了不要block main thread,這個SecItemCopyMatching最好是放到global queue中。



沒有留言:

張貼留言