当前位置: 首页 > 工具软件 > Gatekeeper > 使用案例 >

详解android gatekeeper/fingerprint中的authToken

羊舌高明
2023-12-01

1、authToken是什么?

在密码或指纹验证通过后(verify通过后),需返回一个authToken值,然后交由keystore保持起来. 以下是gatekeeper的verify产生authToken和调用keystore保存authToken的流程图:

2、authToken的填充

在gatekeeper TA的verify()通过后,对填充authToken结构体,然后再返回。

(hardware/libhardware/include/hardware/hw_auth_token.h)
typedef struct __attribute__((__packed__)) {
    uint8_t version;  // Current version is 0
    uint64_t challenge;
    uint64_t user_id;             // secure user ID, not Android user ID
    uint64_t authenticator_id;    // secure authenticator ID
    uint32_t authenticator_type;  // hw_authenticator_type_t, in network order
    uint64_t timestamp;           // in network order
    uint8_t hmac[32];
} hw_auth_token_t;

质询 : challenge
用户SID :user_id
身份验证程序 ID (ASID) : authenticator_id
身份验证程序类型 : authenticator_type,00-gatekeeper,01-指纹

3、authToken的保存

在gatekeeperd中调用hw_device->verify()后,先判断authToken,如果为空,则认为是verify失败(鉴权失败)。如果不为空,则认为verify成功. 并调用addAuthToken将authToken保持下来
以下是authToken的使用逻辑,同底层硬件/TEE无关

在gatekeeperd的verifychallange中hw_device->verify()结束后,调用keystore的addAuthToken方法,将authToken保存下来

(system/core/gatekeeperd$ vim gatekeeperd.cpp)
if (ret == 0 && *auth_token != NULL && *auth_token_length > 0) {
    // TODO: cache service?
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
    sp<security::keystore::IKeystoreService> service =
            interface_cast<security::keystore::IKeystoreService>(binder);
    if (service != NULL) {
        std::vector<uint8_t> auth_token_vector(*auth_token,
                                               (*auth_token) + *auth_token_length);
        int result = 0;
        auto binder_result = service->addAuthToken(auth_token_vector, &result);
        if (!binder_result.isOk() || !keystore::KeyStoreServiceReturnCode(result).isOk()) {
            ALOGE("Failure sending auth token to KeyStore: %" PRId32, result);
        }
    } else {
        ALOGE("Unable to communicate with KeyStore");
    }
}
(frameworks/base/keystore/java/android/security/KeyStore.java)
public int addAuthToken(byte[] authToken) {
    try {
        return mBinder.addAuthToken(authToken);
    } catch (RemoteException e) {
        Log.w(TAG, "Cannot connect to keystore", e);
        return SYSTEM_ERROR;
    }
}
(system/security/keystore/key_store_service.cpp)
Status KeyStoreService::addAuthToken(const ::std::vector<uint8_t>& authTokenAsVector,
                                     int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;

    // TODO(swillden): When gatekeeper and fingerprint are ready, this should be updated to
    // receive a HardwareAuthToken, rather than an opaque byte array.

    if (!checkBinderPermission(P_ADD_AUTH)) {
        ALOGW("addAuthToken: permission denied for %d", IPCThreadState::self()->getCallingUid());
        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
        return Status::ok();
    }
    if (authTokenAsVector.size() != sizeof(hw_auth_token_t)) {
        *aidl_return = KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT).getErrorCode();
        return Status::ok();
    }

    hw_auth_token_t authToken;
    memcpy(reinterpret_cast<void*>(&authToken), authTokenAsVector.data(), sizeof(hw_auth_token_t));
    if (authToken.version != 0) {
        *aidl_return = KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT).getErrorCode();
        return Status::ok();
    }

    mKeyStore->getAuthTokenTable().AddAuthenticationToken(
        hidlVec2AuthToken(hidl_vec<uint8_t>(authTokenAsVector)));
    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
    return Status::ok();
}

max_entries_等于32,authToken的个数小于32,则直接将此authToken压入表中,若大于32则替换一个最小的

(system/security/keystore/auth_token_table.cpp)
void AuthTokenTable::AddAuthenticationToken(HardwareAuthToken&& auth_token) {
    Entry new_entry(std::move(auth_token), clock_function_());
    // STOPSHIP: debug only, to be removed
    ALOGD("AddAuthenticationToken: timestamp = %llu, time_received = %lld",
          static_cast<unsigned long long>(new_entry.token().timestamp),
          static_cast<long long>(new_entry.time_received()));

    std::lock_guard<std::mutex> lock(entries_mutex_);
    RemoveEntriesSupersededBy(new_entry);
    if (entries_.size() >= max_entries_) {
        ALOGW("Auth token table filled up; replacing oldest entry");
        *min_element(entries_) = std::move(new_entry);
    } else {
        entries_.push_back(std::move(new_entry));
    }
}
 类似资料: