/* * Copyright (C) 2017 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. */ #include "OemLock.h" #include #include #include "../apps/boot/include/ese/app/boot.h" #include "ScopedEseConnection.h" namespace android { namespace esed { // libhidl using ::android::hardware::Void; // Methods from ::android::hardware::oemlock::V1_0::IOemLock follow. Return OemLock::getName(getName_cb _hidl_cb) { _hidl_cb(OemLockStatus::OK, {"01"}); return Void(); } Return OemLock::setOemUnlockAllowedByCarrier( bool allowed, const hidl_vec& signature) { LOG(INFO) << "Running OemLock::setOemUnlockAllowedByCarrier: " << allowed; ScopedEseConnection ese{mEse}; ese.init(); // In general, setting the carrier lock to locked is only done in factory, // but there is no reason the HAL could not be used in factory to do it. // As such, the signature would actually be a specially formatted string of // identifiers. Unlocking requires a signature packaged in a simple format // as well. // // See ../apps/boot/README.md for details. std::vector data(signature); // "allowed" == unlocked == 0. uint8_t lock_byte = allowed ? 0 : 1; // xset expects the lock value as the first byte. data.insert(data.cbegin(), lock_byte); // Open SE session for applet EseBootSession session; ese_boot_session_init(&session); EseAppResult res = ese_boot_session_open(mEse.ese_interface(), &session); if (res != ESE_APP_RESULT_OK) { LOG(ERROR) << "Failed to open a boot session: " << res; return OemLockSecureStatus::FAILED; } res = ese_boot_lock_xset(&session, kEseBootLockIdCarrier, data.data(), data.size()); if (res != ESE_APP_RESULT_OK) { LOG(ERROR) << "Failed to change lock state (allowed=" << allowed << "): " << res; } // Try and close the session without perturbing our result value. if (ese_boot_session_close(&session) != ESE_APP_RESULT_OK) { LOG(WARNING) << "Failed to close boot session"; } if (EseAppResultValue(res) == ESE_APP_RESULT_ERROR_APPLET) { // 0004 and 0005 are invalid signature and invalid nonce respectively. return OemLockSecureStatus::INVALID_SIGNATURE; } else if (res != ESE_APP_RESULT_OK) { return OemLockSecureStatus::FAILED; } return OemLockSecureStatus::OK; } Return OemLock::isOemUnlockAllowedByCarrier(isOemUnlockAllowedByCarrier_cb _hidl_cb) { LOG(VERBOSE) << "Running OemLock::isOemUnlockAllowedByCarrier"; ScopedEseConnection ese{mEse}; ese.init(); // Open SE session for applet EseBootSession session; ese_boot_session_init(&session); EseAppResult res = ese_boot_session_open(mEse.ese_interface(), &session); if (res != ESE_APP_RESULT_OK) { LOG(ERROR) << "Failed to open a boot session: " << res; _hidl_cb(OemLockStatus::FAILED, false); return Void(); } std::vector data; data.resize(1024); uint16_t actualData = 0; res = ese_boot_lock_xget(&session, kEseBootLockIdCarrier, &data[0], data.size(), &actualData); if (res != ESE_APP_RESULT_OK || actualData == 0) { LOG(ERROR) << "Failed to get lock state: " << res; } // Try and close the session without perturbing our result value. if (ese_boot_session_close(&session) != ESE_APP_RESULT_OK) { LOG(WARNING) << "Failed to close boot session"; } if (res != ESE_APP_RESULT_OK) { // Fail closed. _hidl_cb(OemLockStatus::FAILED, false); return Void(); } // if data[0] == 1, lock == true, so allowed == false. _hidl_cb(OemLockStatus::OK, data[0] != 0 ? false : true); return Void(); } Return OemLock::setOemUnlockAllowedByDevice(bool allowed) { LOG(INFO) << "Running OemLock::setOemUnlockAllowedByDevice: " << allowed; ScopedEseConnection ese{mEse}; ese.init(); // "allowed" == unlocked == 0. uint8_t lock_byte = allowed ? 0 : 1; // Open SE session for applet EseBootSession session; ese_boot_session_init(&session); EseAppResult res = ese_boot_session_open(mEse.ese_interface(), &session); if (res != ESE_APP_RESULT_OK) { LOG(ERROR) << "Failed to open a boot session: " << res; return OemLockStatus::FAILED; } res = ese_boot_lock_set(&session, kEseBootLockIdDevice, lock_byte); if (res != ESE_APP_RESULT_OK) { LOG(ERROR) << "Failed to change device lock state (allowed=" << allowed << "): " << res; } // Try and close the session without perturbing our result value. if (ese_boot_session_close(&session) != ESE_APP_RESULT_OK) { LOG(WARNING) << "Failed to close boot session"; } if (res != ESE_APP_RESULT_OK) { return OemLockStatus::FAILED; } return OemLockStatus::OK; } Return OemLock::isOemUnlockAllowedByDevice(isOemUnlockAllowedByDevice_cb _hidl_cb) { LOG(VERBOSE) << "Running OemLock::isOemUnlockAllowedByDevice"; ScopedEseConnection ese{mEse}; ese.init(); // Open SE session for applet EseBootSession session; ese_boot_session_init(&session); EseAppResult res = ese_boot_session_open(mEse.ese_interface(), &session); if (res != ESE_APP_RESULT_OK) { LOG(ERROR) << "Failed to open a boot session: " << res; _hidl_cb(OemLockStatus::FAILED, false); return Void(); } uint8_t lock_byte = 0; res = ese_boot_lock_get(&session, kEseBootLockIdDevice, &lock_byte); if (res != ESE_APP_RESULT_OK) { LOG(ERROR) << "Failed to get device lock state: " << res; } // Try and close the session without perturbing our result value. if (ese_boot_session_close(&session) != ESE_APP_RESULT_OK) { LOG(WARNING) << "Failed to close boot session"; } if (res != ESE_APP_RESULT_OK) { // Fail closed. _hidl_cb(OemLockStatus::FAILED, false); return Void(); } // if data[0] == 1, lock == true, so allowed == false. _hidl_cb(OemLockStatus::OK, lock_byte != 0 ? false : true); return Void(); } } // namespace esed } // namespace android