Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e180ec52 authored by Janis Danisevskis's avatar Janis Danisevskis Committed by Gerrit Code Review
Browse files

Merge changes from topic "gatekeeper_maintenance"

* changes:
  Replace legacy trusty gatekeeper HAL with HIDLized version
  Gatekeeperd maintenance
parents c4117afd 7daa66aa
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -23,8 +23,6 @@ cc_binary {
        "-Wunused",
    ],
    srcs: [
        "SoftGateKeeperDevice.cpp",
        "IGateKeeperService.cpp",
        "gatekeeperd.cpp",
    ],

@@ -43,9 +41,44 @@ cc_binary {
        "libhidltransport",
        "libhwbinder",
        "android.hardware.gatekeeper@1.0",
        "libgatekeeper_aidl",
    ],

    static_libs: ["libscrypt_static"],
    include_dirs: ["external/scrypt/lib/crypto"],
    init_rc: ["gatekeeperd.rc"],
}

filegroup {
    name: "gatekeeper_aidl",
    srcs: [
        "binder/android/service/gatekeeper/IGateKeeperService.aidl",
    ],
    path: "binder",
}

cc_library_shared {
    name: "libgatekeeper_aidl",
    srcs: [
        ":gatekeeper_aidl",
        "GateKeeperResponse.cpp",
    ],
    aidl: {
        export_aidl_headers: true,
        include_dirs: [
            "system/core/gatekeeperd/binder",
            "frameworks/base/core/java/",
        ],
    },
    export_include_dirs: ["include"],
    shared_libs: [
        "libbase",
        "libbinder",
        "libcutils",
        "liblog",
        "libutils",
    ],
    export_shared_lib_headers: [
        "libbinder",
    ],
}
+83 −0
Original line number Diff line number Diff line
/*
**
** Copyright 2019, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#define LOG_TAG "gatekeeperd"

#include <gatekeeper/GateKeeperResponse.h>

#include <binder/Parcel.h>

#include <android-base/logging.h>

namespace android {
namespace service {
namespace gatekeeper {

status_t GateKeeperResponse::readFromParcel(const Parcel* in) {
    if (in == nullptr) {
        LOG(ERROR) << "readFromParcel got null in parameter";
        return BAD_VALUE;
    }
    timeout_ = 0;
    should_reenroll_ = false;
    payload_ = {};
    response_code_ = ResponseCode(in->readInt32());
    if (response_code_ == ResponseCode::OK) {
        should_reenroll_ = in->readInt32();
        ssize_t length = in->readInt32();
        if (length > 0) {
            length = in->readInt32();
            const uint8_t* buf = reinterpret_cast<const uint8_t*>(in->readInplace(length));
            if (buf == nullptr) {
                LOG(ERROR) << "readInplace returned null buffer for length " << length;
                return BAD_VALUE;
            }
            payload_.resize(length);
            std::copy(buf, buf + length, payload_.data());
        }
    } else if (response_code_ == ResponseCode::RETRY) {
        timeout_ = in->readInt32();
    }
    return NO_ERROR;
}
status_t GateKeeperResponse::writeToParcel(Parcel* out) const {
    if (out == nullptr) {
        LOG(ERROR) << "writeToParcel got null out parameter";
        return BAD_VALUE;
    }
    out->writeInt32(int32_t(response_code_));
    if (response_code_ == ResponseCode::OK) {
        out->writeInt32(should_reenroll_);
        out->writeInt32(payload_.size());
        if (payload_.size() != 0) {
            out->writeInt32(payload_.size());
            uint8_t* buf = reinterpret_cast<uint8_t*>(out->writeInplace(payload_.size()));
            if (buf == nullptr) {
                LOG(ERROR) << "writeInplace returned null buffer for length " << payload_.size();
                return BAD_VALUE;
            }
            std::copy(payload_.begin(), payload_.end(), buf);
        }
    } else if (response_code_ == ResponseCode::RETRY) {
        out->writeInt32(timeout_);
    }
    return NO_ERROR;
}

}  // namespace gatekeeper
}  // namespace service
}  // namespace android
+0 −173
Original line number Diff line number Diff line
/*
 * Copyright 2015, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

#define LOG_TAG "GateKeeperService"
#include <utils/Log.h>

#include "IGateKeeperService.h"

namespace android {

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: {
            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;

            bool request_reenroll = false;
            int ret = verify(uid, (uint8_t *) currentPasswordHandle,
                    currentPasswordHandleSize, (uint8_t *) currentPassword, currentPasswordSize,
                    &request_reenroll);

            reply->writeNoException();
            reply->writeInt32(1);
            if (ret == 0) {
                reply->writeInt32(GATEKEEPER_RESPONSE_OK);
                reply->writeInt32(request_reenroll ? 1 : 0);
                reply->writeInt32(0); // no payload returned from this call
            } else if (ret > 0) {
                reply->writeInt32(GATEKEEPER_RESPONSE_RETRY);
                reply->writeInt32(ret);
            } else {
                reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
            }
            return OK;
        }
        case VERIFY_CHALLENGE: {
            CHECK_INTERFACE(IGateKeeperService, data, reply);
            uint32_t uid = data.readInt32();
            uint64_t challenge = data.readInt64();
            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;


            uint8_t *out = NULL;
            uint32_t outSize = 0;
            bool request_reenroll = false;
            int ret = verifyChallenge(uid, challenge, (uint8_t *) currentPasswordHandle,
                    currentPasswordHandleSize, (uint8_t *) currentPassword, currentPasswordSize,
                    &out, &outSize, &request_reenroll);
            reply->writeNoException();
            reply->writeInt32(1);
            if (ret == 0 && outSize > 0 && out != NULL) {
                reply->writeInt32(GATEKEEPER_RESPONSE_OK);
                reply->writeInt32(request_reenroll ? 1 : 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 GET_SECURE_USER_ID: {
            CHECK_INTERFACE(IGateKeeperService, data, reply);
            uint32_t uid = data.readInt32();
            uint64_t sid = getSecureUserId(uid);
            reply->writeNoException();
            reply->writeInt64(sid);
            return OK;
        }
        case CLEAR_SECURE_USER_ID: {
            CHECK_INTERFACE(IGateKeeperService, data, reply);
            uint32_t uid = data.readInt32();
            clearSecureUserId(uid);
            reply->writeNoException();
            return OK;
        }
        case REPORT_DEVICE_SETUP_COMPLETE: {
            CHECK_INTERFACE(IGateKeeperService, data, reply);
            reportDeviceSetupComplete();
            reply->writeNoException();
            return OK;
        }
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
};


}; // namespace android

gatekeeperd/IGateKeeperService.h

deleted100644 → 0
+0 −118
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef IGATEKEEPER_SERVICE_H_
#define IGATEKEEPER_SERVICE_H_

#include <binder/IInterface.h>
#include <binder/Parcel.h>

namespace android {

/*
 * This must be kept manually in sync with frameworks/base's IGateKeeperService.aidl
 */
class IGateKeeperService : public IInterface {
public:
    enum {
        ENROLL = IBinder::FIRST_CALL_TRANSACTION + 0,
        VERIFY = IBinder::FIRST_CALL_TRANSACTION + 1,
        VERIFY_CHALLENGE = IBinder::FIRST_CALL_TRANSACTION + 2,
        GET_SECURE_USER_ID = IBinder::FIRST_CALL_TRANSACTION + 3,
        CLEAR_SECURE_USER_ID = IBinder::FIRST_CALL_TRANSACTION + 4,
        REPORT_DEVICE_SETUP_COMPLETE = IBinder::FIRST_CALL_TRANSACTION + 5,
    };

    enum {
        GATEKEEPER_RESPONSE_OK = 0,
        GATEKEEPER_RESPONSE_RETRY = 1,
        GATEKEEPER_RESPONSE_ERROR = -1,
    };

    // DECLARE_META_INTERFACE - C++ client interface not needed
    static const android::String16 descriptor;
    virtual const android::String16& getInterfaceDescriptor() const;
    IGateKeeperService() {}
    virtual ~IGateKeeperService() {}

    /**
     * Enrolls a password with the GateKeeper. Returns 0 on success, negative on failure.
     * Returns:
     * - 0 on success
     * - A timestamp T > 0 if the call has failed due to throttling and should not
     *   be reattempted until T milliseconds have elapsed
     * - -1 on failure
     */
    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) = 0;

    /**
     * Verifies a password previously enrolled with the GateKeeper.
     * Returns:
     * - 0 on success
     * - A timestamp T > 0 if the call has failed due to throttling and should not
     *   be reattempted until T milliseconds have elapsed
     * - -1 on failure
     */
    virtual int verify(uint32_t uid, const uint8_t *enrolled_password_handle,
            uint32_t enrolled_password_handle_length,
            const uint8_t *provided_password, uint32_t provided_password_length,
            bool *request_reenroll) = 0;

    /**
     * Verifies a password previously enrolled with the GateKeeper.
     * Returns:
     * - 0 on success
     * - A timestamp T > 0 if the call has failed due to throttling and should not
     *   be reattempted until T milliseconds have elapsed
     * - -1 on failure
     */
    virtual int verifyChallenge(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) = 0;
    /**
     * Returns the secure user ID for the provided android user
     */
    virtual uint64_t getSecureUserId(uint32_t uid) = 0;

    /**
     * Clears the secure user ID associated with the user.
     */
    virtual void clearSecureUserId(uint32_t uid) = 0;

    /**
     * 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).
     */
    virtual void reportDeviceSetupComplete() = 0;
};

// ----------------------------------------------------------------------------

class BnGateKeeperService: public BnInterface<IGateKeeperService> {
public:
    virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
            uint32_t flags = 0);
};

} // namespace android

#endif

gatekeeperd/SoftGateKeeper.h

deleted100644 → 0
+0 −182
Original line number Diff line number Diff line
/*
 * Copyright 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef SOFT_GATEKEEPER_H_
#define SOFT_GATEKEEPER_H_

extern "C" {
#include <openssl/rand.h>
#include <openssl/sha.h>

#include <crypto_scrypt.h>
}

#include <android-base/memory.h>
#include <gatekeeper/gatekeeper.h>

#include <iostream>
#include <unordered_map>
#include <memory>

namespace gatekeeper {

struct fast_hash_t {
    uint64_t salt;
    uint8_t digest[SHA256_DIGEST_LENGTH];
};

class SoftGateKeeper : public GateKeeper {
public:
    static const uint32_t SIGNATURE_LENGTH_BYTES = 32;

    // scrypt params
    static const uint64_t N = 16384;
    static const uint32_t r = 8;
    static const uint32_t p = 1;

    static const int MAX_UINT_32_CHARS = 11;

    SoftGateKeeper() {
        key_.reset(new uint8_t[SIGNATURE_LENGTH_BYTES]);
        memset(key_.get(), 0, SIGNATURE_LENGTH_BYTES);
    }

    virtual ~SoftGateKeeper() {
    }

    virtual bool GetAuthTokenKey(const uint8_t **auth_token_key,
            uint32_t *length) const {
        if (auth_token_key == NULL || length == NULL) return false;
        uint8_t *auth_token_key_copy = new uint8_t[SIGNATURE_LENGTH_BYTES];
        memcpy(auth_token_key_copy, key_.get(), SIGNATURE_LENGTH_BYTES);

        *auth_token_key = auth_token_key_copy;
        *length = SIGNATURE_LENGTH_BYTES;
        return true;
    }

    virtual void GetPasswordKey(const uint8_t **password_key, uint32_t *length) {
        if (password_key == NULL || length == NULL) return;
        uint8_t *password_key_copy = new uint8_t[SIGNATURE_LENGTH_BYTES];
        memcpy(password_key_copy, key_.get(), SIGNATURE_LENGTH_BYTES);

        *password_key = password_key_copy;
        *length = SIGNATURE_LENGTH_BYTES;
    }

    virtual void ComputePasswordSignature(uint8_t *signature, uint32_t signature_length,
            const uint8_t *, uint32_t, const uint8_t *password,
            uint32_t password_length, salt_t salt) const {
        if (signature == NULL) return;
        crypto_scrypt(password, password_length, reinterpret_cast<uint8_t *>(&salt),
                sizeof(salt), N, r, p, signature, signature_length);
    }

    virtual void GetRandom(void *random, uint32_t requested_length) const {
        if (random == NULL) return;
        RAND_pseudo_bytes((uint8_t *) random, requested_length);
    }

    virtual void ComputeSignature(uint8_t *signature, uint32_t signature_length,
            const uint8_t *, uint32_t, const uint8_t *, const uint32_t) const {
        if (signature == NULL) return;
        memset(signature, 0, signature_length);
    }

    virtual uint64_t GetMillisecondsSinceBoot() const {
        struct timespec time;
        int res = clock_gettime(CLOCK_BOOTTIME, &time);
        if (res < 0) return 0;
        return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000);
    }

    virtual bool IsHardwareBacked() const {
        return false;
    }

    virtual bool GetFailureRecord(uint32_t uid, secure_id_t user_id, failure_record_t *record,
            bool /* secure */) {
        failure_record_t *stored = &failure_map_[uid];
        if (user_id != stored->secure_user_id) {
            stored->secure_user_id = user_id;
            stored->last_checked_timestamp = 0;
            stored->failure_counter = 0;
        }
        memcpy(record, stored, sizeof(*record));
        return true;
    }

    virtual bool ClearFailureRecord(uint32_t uid, secure_id_t user_id, bool /* secure */) {
        failure_record_t *stored = &failure_map_[uid];
        stored->secure_user_id = user_id;
        stored->last_checked_timestamp = 0;
        stored->failure_counter = 0;
        return true;
    }

    virtual bool WriteFailureRecord(uint32_t uid, failure_record_t *record, bool /* secure */) {
        failure_map_[uid] = *record;
        return true;
    }

    fast_hash_t ComputeFastHash(const SizedBuffer &password, uint64_t salt) {
        fast_hash_t fast_hash;
        size_t digest_size = password.length + sizeof(salt);
        std::unique_ptr<uint8_t[]> digest(new uint8_t[digest_size]);
        memcpy(digest.get(), &salt, sizeof(salt));
        memcpy(digest.get() + sizeof(salt), password.buffer.get(), password.length);

        SHA256(digest.get(), digest_size, (uint8_t *) &fast_hash.digest);

        fast_hash.salt = salt;
        return fast_hash;
    }

    bool VerifyFast(const fast_hash_t &fast_hash, const SizedBuffer &password) {
        fast_hash_t computed = ComputeFastHash(password, fast_hash.salt);
        return memcmp(computed.digest, fast_hash.digest, SHA256_DIGEST_LENGTH) == 0;
    }

    bool DoVerify(const password_handle_t *expected_handle, const SizedBuffer &password) {
        uint64_t user_id = android::base::get_unaligned<secure_id_t>(&expected_handle->user_id);
        FastHashMap::const_iterator it = fast_hash_map_.find(user_id);
        if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) {
            return true;
        } else {
            if (GateKeeper::DoVerify(expected_handle, password)) {
                uint64_t salt;
                GetRandom(&salt, sizeof(salt));
                fast_hash_map_[user_id] = ComputeFastHash(password, salt);
                return true;
            }
        }

        return false;
    }

private:

    typedef std::unordered_map<uint32_t, failure_record_t> FailureRecordMap;
    typedef std::unordered_map<uint64_t, fast_hash_t> FastHashMap;

    std::unique_ptr<uint8_t[]> key_;
    FailureRecordMap failure_map_;
    FastHashMap fast_hash_map_;
};
}

#endif // SOFT_GATEKEEPER_H_
Loading