You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
6.7 KiB
189 lines
6.7 KiB
/* |
|
* 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 <vector> |
|
|
|
#include <android-base/logging.h> |
|
#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<void> OemLock::getName(getName_cb _hidl_cb) { |
|
_hidl_cb(OemLockStatus::OK, {"01"}); |
|
return Void(); |
|
} |
|
|
|
Return<OemLockSecureStatus> OemLock::setOemUnlockAllowedByCarrier( |
|
bool allowed, const hidl_vec<uint8_t>& 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<uint8_t> 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<void> 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<uint8_t> 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<OemLockStatus> 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<void> 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
|
|
|