Android gatekeeper的原理介绍和代码导读

快速链接:
.
👉👉👉 个人博客笔记导读目录(全部) 👈👈👈


说明: 本文已抛弃,请移步到Android Gatekeeper流程深度解剖查看

一、gatekeeper
1、gatekeeper的软件框图

gatekeeper的代码共有7部分:

  • frameworks/base/services/core/java/com/android/server/locksettings/ : 上层locksetting APP的实现
  • frameworks/base/core/java/android/service/gatekeeper/IGateKeeperService.aidl : AIDL语言的描述(IGateKeeperService)
  • system/core/gatekeeperd : 守护进程gatekeeperd, IGateKeeperService的实现
  • system/gatekeeper : gatekeeper的纯软实现
  • hardware/interfaces/gatekeeper : gatekeeper的hidl实现
  • vendor gatekeeper hal : vendor厂商ovreride实现的gatekeeper hal
  • gatekeeper TA : gatekeeper的TA代码
    (软件流程图)
    在这里插入图片描述
    (代码结构图)
    在这里插入图片描述
2、gatekeeper的代码导读

(1)、locksettings : 就是密码锁/图案锁的APP,该程序直接调用IGateKeeperService的aidl
(frameworks/base/services/core/java/com/android/server/locksettings/)

例如在createPasswordBasedSyntheticPassword方法中,调用了IGateKeeperService gatekeeper的gatekeeper.enroll方法;

public long createPasswordBasedSyntheticPassword(IGateKeeperService gatekeeper,
        byte[] credential, int credentialType, AuthenticationToken authToken,
        int requestedQuality, int userId)
                throws RemoteException {
    if (credential == null || credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
        credentialType = LockPatternUtils.CREDENTIAL_TYPE_NONE;
        credential = DEFAULT_PASSWORD;
    }

    long handle = generateHandle();
    PasswordData pwd = PasswordData.create(credentialType);
    byte[] pwdToken = computePasswordToken(credential, pwd);
    final long sid;
    final byte[] applicationId;

    if (isWeaverAvailable()) {
        // Weaver based user password
        int weaverSlot = getNextAvailableWeaverSlot();
        Log.i(TAG, "Weaver enroll password to slot " + weaverSlot + " for user " + userId);
        byte[] weaverSecret = weaverEnroll(weaverSlot, passwordTokenToWeaverKey(pwdToken), null);
        if (weaverSecret == null) {
            Log.e(TAG, "Fail to enroll user password under weaver " + userId);
            return DEFAULT_HANDLE;
        }
        saveWeaverSlot(weaverSlot, handle, userId);
        mPasswordSlotManager.markSlotInUse(weaverSlot);
        synchronizeWeaverFrpPassword(pwd, requestedQuality, userId, weaverSlot);

        pwd.passwordHandle = null;
        sid = GateKeeper.INVALID_SECURE_USER_ID;
        applicationId = transformUnderWeaverSecret(pwdToken, weaverSecret);
    } else {
        // In case GK enrollment leaves persistent state around (in RPMB), this will nuke them
        // to prevent them from accumulating and causing problems.
        gatekeeper.clearSecureUserId(fakeUid(userId));
        // GateKeeper based user password
        GateKeeperResponse response = gatekeeper.enroll(fakeUid(userId), null, null,
                passwordTokenToGkInput(pwdToken));
        if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) {
            Log.e(TAG, "Fail to enroll user password when creating SP for user " + userId);
            return DEFAULT_HANDLE;
        }
        pwd.passwordHandle = response.getPayload();
        sid = sidFromPasswordHandle(pwd.passwordHandle);
        applicationId = transformUnderSecdiscardable(pwdToken,
                createSecdiscardable(handle, userId));
        synchronizeFrpPassword(pwd, requestedQuality, userId);
    }
    saveState(PASSWORD_DATA_NAME, pwd.toBytes(), handle, userId);

    createSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_PASSWORD_BASED, authToken,
            applicationId, sid, userId);
    return handle;
}

(2)、在IGateKeeperService的aidl中描述了IGateKeeperService;
(frameworks/base/core/java/android/service/gatekeeper/IGateKeeperService.aidl)

interface IGateKeeperService {
    /**
     * Enrolls a password, returning the handle to the enrollment to be stored locally.
     * @param uid The Android user ID associated to this enrollment
     * @param currentPasswordHandle The previously enrolled handle, or null if none
     * @param currentPassword The previously enrolled plaintext password, or null if none.
     *                        If provided, must verify against the currentPasswordHandle.
     * @param desiredPassword The new desired password, for which a handle will be returned
     *                        upon success.
     * @return an EnrollResponse or null on failure
     */
    GateKeeperResponse enroll(int uid, in byte[] currentPasswordHandle, in byte[] currentPassword,
            in byte[] desiredPassword);

    /**
     * Verifies an enrolled handle against a provided, plaintext blob.
     * @param uid The Android user ID associated to this enrollment
     * @param enrolledPasswordHandle The handle against which the provided password will be
     *                               verified.
     * @param The plaintext blob to verify against enrolledPassword.
     * @return a VerifyResponse, or null on failure.
     */
    GateKeeperResponse verify(int uid, in byte[] enrolledPasswordHandle, in byte[] providedPassword);

    /**
     * Verifies an enrolled handle against a provided, plaintext blob.
     * @param uid The Android user ID associated to this enrollment
     * @param challenge a challenge to authenticate agaisnt the device credential. If successful
     *                  authentication occurs, this value will be written to the returned
     *                  authentication attestation.
     * @param enrolledPasswordHandle The handle against which the provided password will be
     *                               verified.
     * @param The plaintext blob to verify against enrolledPassword.
     * @return a VerifyResponse with an attestation, or null on failure.
     */
    GateKeeperResponse verifyChallenge(int uid, long challenge, in byte[] enrolledPasswordHandle,
            in byte[] providedPassword);

    /**
     * Retrieves the secure identifier for the user with the provided Android ID,
     * or 0 if none is found.
     * @param uid the Android user id
     */
    long getSecureUserId(int uid);

    /**
     * Clears secure user id associated with the provided Android ID.
     * Must be called when password is set to NONE.
     * @param uid the Android user id.
     */
    void clearSecureUserId(int uid);

    /**
     * Notifies gatekeeper that device setup has been completed and any potentially still existing
     * state from before a factory reset can be cleaned up (if it has not been already).
     */
    void reportDeviceSetupComplete();
}

(3)、在gatekeeperd中实现了IGateKeeperService,并在gatekeeper的main函数中,添加了这个service
(system/core/gatekeeperd/IGateKeeperService.cpp)

const android::String16 IGateKeeperService::descriptor("android.service.gatekeeper.IGateKeeperService");
const android::String16& IGateKeeperService::getInterfaceDescriptor() const {
    return IGateKeeperService::descriptor;
}

status_t BnGateKeeperService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
    switch(code) {
        case ENROLL: {
            CHECK_INTERFACE(IGateKeeperService, data, reply);
            uint32_t uid = data.readInt32();

            ssize_t currentPasswordHandleSize = data.readInt32();
            const uint8_t *currentPasswordHandle =
                    static_cast<const uint8_t *>(data.readInplace(currentPasswordHandleSize));
            if (!currentPasswordHandle) currentPasswordHandleSize = 0;

            ssize_t currentPasswordSize = data.readInt32();
            const uint8_t *currentPassword =
                    static_cast<const uint8_t *>(data.readInplace(currentPasswordSize));
            if (!currentPassword) currentPasswordSize = 0;

            ssize_t desiredPasswordSize = data.readInt32();
            const uint8_t *desiredPassword =
                    static_cast<const uint8_t *>(data.readInplace(desiredPasswordSize));
            if (!desiredPassword) desiredPasswordSize = 0;

            uint8_t *out = NULL;
            uint32_t outSize = 0;
            int ret = enroll(uid, currentPasswordHandle, currentPasswordHandleSize,
                    currentPassword, currentPasswordSize, desiredPassword,
                    desiredPasswordSize, &out, &outSize);

            reply->writeNoException();
            reply->writeInt32(1);
            if (ret == 0 && outSize > 0 && out != NULL) {
                reply->writeInt32(GATEKEEPER_RESPONSE_OK);
                reply->writeInt32(0);
                reply->writeInt32(outSize);
                reply->writeInt32(outSize);
                void *buf = reply->writeInplace(outSize);
                memcpy(buf, out, outSize);
                delete[] out;
            } else if (ret > 0) {
                reply->writeInt32(GATEKEEPER_RESPONSE_RETRY);
                reply->writeInt32(ret);
            } else {
                reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
            }
            return OK;
        }
        case VERIFY: {
......
         }
         case VERIFY_CHALLENGE: {
......
        }
        case GET_SECURE_USER_ID: {
......
        }
        case CLEAR_SECURE_USER_ID: {
......
        }
        case REPORT_DEVICE_SETUP_COMPLETE: {
......
        }
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
};

(4)、在的switch case中,调用了gatekeeprd.cpp中的中间函数,以enroll为例
在该函数中,如果硬件hal实现了,则会调用硬件实现的方法,否则调用纯软件逻辑
(system/core/gatekeeperd/gatekeeperd.cpp)

virtual int enroll(uint32_t uid,
        const uint8_t *current_password_handle, uint32_t current_password_handle_length,
        const uint8_t *current_password, uint32_t current_password_length,
        const uint8_t *desired_password, uint32_t desired_password_length,
        uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
......
    if (hw_device != nullptr) {
......
        Return<void> hwRes = hw_device->enroll(hw_uid, curPwdHandle, curPwd, newPwd,
                          [&ret, enrolled_password_handle, enrolled_password_handle_length]
                               (const GatekeeperResponse &rsp) {
......
    } else {
        ret = soft_device->enroll(uid,
                current_password_handle, current_password_handle_length,
                current_password, current_password_length,
                desired_password, desired_password_length,
                enrolled_password_handle, enrolled_password_handle_length);
    }
......
}

(5)、在vendor实现的硬件gatekeeper hal接口中,会发送调用去调用gatekeeper TA
在中调用了TEEC_InvokeCommand,发送命令到TA中干活.
(vendor/mediatek/proprietary/trustzone/microtrust/source/common/300/gatekeeper/ut_gatekeeper.cpp)

static int ut_gk_enroll(const struct gatekeeper_device* dev, uint32_t uid,
                        const uint8_t* current_password_handle,
                        uint32_t current_password_handle_length, const uint8_t* current_password,
                        uint32_t current_password_length, const uint8_t* desired_password,
                        uint32_t desired_password_length, uint8_t** enrolled_password_handle,
                        uint32_t* enrolled_password_handle_length)
{
......
    if (!ut_gk_transfer_buff(gatekeeper_transfer_buffer))
......
    return ret;
}
3、gatekeeper的总结
  • 在首次enroll的时候,传入密码,到TEE(TA)中填充password_handle_t结构体(version,userid,flags,salt,signature,hardware_backed),然后返回这个结构体,交由android保存.
  • 在verify的时候, 传入密码和android中之前保存的password_handle_t数据,到(TA)中去验证密码.
    TEE验证成功后,则返回AuthToken.
    android端拿到authToken后,还会再调用keymaster验证authtoken的合法性.
  • 在修改密码时,传入原来的密码、password_handle_t、新密码,到TEE中,先校验原来的密码,成功后TEE对新密码签名,然后填充password_handle_t结构体,返回给android重新保存
3、gatekeeper的hal分析

主要看enroll和verify函数:

(函数原型)
int (*enroll)(const struct gatekeeper_device *dev, uint32_t uid,
        const uint8_t *current_password_handle, uint32_t current_password_handle_length,
        const uint8_t *current_password, uint32_t current_password_length,
        const uint8_t *desired_password, uint32_t desired_password_length,
        uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length);

int (*verify)(const struct gatekeeper_device *dev, uint32_t uid, uint64_t challenge,
         const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
         const uint8_t *provided_password, uint32_t provided_password_length,
         uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll);

password参数解释:
【enroll】
current_password_handle : 注册信息, 第一次注册时为空
current_password : 原来的密码(需要验证的密码),第一次注册时为空
desired_password : 录入的密码
enrolled_password_handle : 返回给android的注册信息,需要android来保存

【verify】
enrolled_password_handle : 当前的注册信息
provided_password : 需要验证的密码

enroll的返回信息,也就是对enrolled_password_handle变量的填充

填充的类型:
system/gatekeeper/include/gatekeeper/password_handle.h
struct attribute ((packed)) password_handle_t {
uint8_t version;
secure_id_t user_id;
uint64_t flags;
salt_t salt;
uint8_t signature[32];
bool hardware_backed;
};

TEE中的填充方法:
enrolled_password_handle->version = handle_version
enrolled_password_handle->salt = salt
enrolled_password_handle->user_id = user_id
enrolled_password_handle->flags = flags
enrolled_password_handle->hardware_backed = gkbase->IsHardwareBacked()
enrolled_password_handle->signature

解释:
handle_version : 在tee中写死的2
salt : 每次enroll时,在tee中GetRandom随机生成
user_id : 第一次enroll时,在tee中GetRandom随机生成.其实就是SID
flags : throttle flag
hardware_backed : 为1
signature : 对密码的签名后数据

二、fingerprint
三、face
四、总结

(1)、上层一些程序的总结
(service) 路径
frameworks/base/services/core/java/com/android/server/locksettings/

LockSettingsService.java       LockSettingsStorage.java     PasswordSlotManager.java  SyntheticPasswordCrypto.java   recoverablekeystore
LockSettingsShellCommand.java  LockSettingsStrongAuth.java  SP800Derive.java          SyntheticPasswordManager.java

frameworks/base/services/core/java/com/android/server/biometrics/fingerprint/

FingerprintConstants.java  FingerprintService.java  FingerprintUserState.java  FingerprintUtils.java

frameworks/base/services/core/java/com/android/server/biometrics/face/

FaceConstants.java  FaceService.java  FaceUserState.java  FaceUtils.java

(Manager) 路径
frameworks/base/services/core/java/com/android/server/locksettings/

LockSettingsService.java       LockSettingsStorage.java     PasswordSlotManager.java  SyntheticPasswordCrypto.java   recoverablekeystore
LockSettingsShellCommand.java  LockSettingsStrongAuth.java  SP800Derive.java          SyntheticPasswordManager.java

(AIDL) 路径
frameworks/base/core/java/android/service/gatekeeper

GateKeeperResponse.aidl  GateKeeperResponse.java  IGateKeeperService.aidl

frameworks/base/core/java/android/hardware/face/

Fingerprint.aidl  Fingerprint.java  FingerprintManager.java  IFingerprintClientActiveCallback.aidl  IFingerprintService.aidl  IFingerprintServiceReceiver.aidl

frameworks/base/core/java/android/hardware/fingerprint/

Face.aidl  Face.java  FaceManager.java  IFaceService.aidl  IFaceServiceReceiver.aidl
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
gatekeeper是指在计算机系统中,用于限制用户对系统资源的访问权限的一种软件或硬件机制。它可以作为一个安全门禁,确保只有经过授权的用户可以使用系统资源。这种机制可以帮助保护系统免受未经授权或恶意访问的威胁。通过对用户身份进行验证,gatekeeper可以决定是否允许用户访问系统中的敏感数据、配置设置和其他资源。 TrustZone是一种基于硬件的安全技术,用于提供比常规软件安全性更高的保护。它将处理器分为不同的安全域,每个安全域都有自己的内存和处理器资源。TrustZone可以将系统划分为一个安全域和一个非安全域,这样可以确保安全域中的软件和数据不受非安全域的干扰。非安全域运行一般应用程序,而安全域用于运行敏感数据和关键任务的应用程序。 TrustZone可以保护诸如加密密钥、身份验证和数字签名等敏感信息,从而防止未经授权的访问和攻击。它还可以防止恶意软件或操作系统级别的漏洞对敏感数据的访问。TrustZone提供了硬件级别的安全隔离,确保安全域中的软件和数据不会受到来自非安全域的干扰。 综上所述,gatekeeper和TrustZone都是用于提高计算机系统安全性的机制。Gatekeeper通过对用户身份验证和权限控制来限制对系统资源的访问,而TrustZone通过硬件级别的安全域划分和隔离,提供更高级别的安全保护。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码改变世界ctw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值