Will Drewry | e47ba83 | 2017-04-18 17:08:09 -0500 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2017 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include "OemLock.h" |
| 18 | |
| 19 | #include <vector> |
| 20 | |
| 21 | #include <android-base/logging.h> |
| 22 | #include "../apps/boot/include/ese/app/boot.h" |
| 23 | #include "ScopedEseConnection.h" |
| 24 | |
| 25 | namespace android { |
| 26 | namespace esed { |
| 27 | |
| 28 | // libhidl |
| 29 | using ::android::hardware::Void; |
| 30 | |
| 31 | // Methods from ::android::hardware::oemlock::V1_0::IOemLock follow. |
| 32 | Return<void> OemLock::getName(getName_cb _hidl_cb) { |
| 33 | _hidl_cb(OemLockStatus::OK, {"01"}); |
| 34 | return Void(); |
| 35 | } |
| 36 | |
| 37 | Return<OemLockSecureStatus> OemLock::setOemUnlockAllowedByCarrier( |
| 38 | bool allowed, const hidl_vec<uint8_t>& signature) { |
| 39 | LOG(INFO) << "Running OemLock::setOemUnlockAllowedByCarrier: " << allowed; |
| 40 | ScopedEseConnection ese{mEse}; |
| 41 | ese.init(); |
| 42 | // In general, setting the carrier lock to locked is only done in factory, |
| 43 | // but there is no reason the HAL could not be used in factory to do it. |
| 44 | // As such, the signature would actually be a specially formatted string of |
| 45 | // identifiers. Unlocking requires a signature packaged in a simple format |
| 46 | // as well. |
| 47 | // |
| 48 | // See ../apps/boot/README.md for details. |
| 49 | std::vector<uint8_t> data(signature); |
| 50 | // "allowed" == unlocked == 0. |
| 51 | uint8_t lock_byte = allowed ? 0 : 1; |
| 52 | // xset expects the lock value as the first byte. |
| 53 | data.insert(data.cbegin(), lock_byte); |
| 54 | |
| 55 | // Open SE session for applet |
| 56 | EseBootSession session; |
| 57 | ese_boot_session_init(&session); |
| 58 | EseAppResult res = ese_boot_session_open(mEse.ese_interface(), &session); |
| 59 | if (res != ESE_APP_RESULT_OK) { |
| 60 | LOG(ERROR) << "Failed to open a boot session: " << res; |
| 61 | return OemLockSecureStatus::FAILED; |
| 62 | } |
| 63 | res = ese_boot_lock_xset(&session, kEseBootLockIdCarrier, |
| 64 | data.data(), data.size()); |
| 65 | if (res != ESE_APP_RESULT_OK) { |
| 66 | LOG(ERROR) << "Failed to change lock state (allowed=" |
| 67 | << allowed << "): " << res; |
| 68 | } |
| 69 | |
| 70 | // Try and close the session without perturbing our result value. |
| 71 | if (ese_boot_session_close(&session) != ESE_APP_RESULT_OK) { |
| 72 | LOG(WARNING) << "Failed to close boot session"; |
| 73 | } |
| 74 | |
| 75 | if (EseAppResultValue(res) == ESE_APP_RESULT_ERROR_APPLET) { |
| 76 | // 0004 and 0005 are invalid signature and invalid nonce respectively. |
| 77 | return OemLockSecureStatus::INVALID_SIGNATURE; |
| 78 | } else if (res != ESE_APP_RESULT_OK) { |
| 79 | return OemLockSecureStatus::FAILED; |
| 80 | } |
| 81 | return OemLockSecureStatus::OK; |
| 82 | } |
| 83 | |
| 84 | Return<void> OemLock::isOemUnlockAllowedByCarrier(isOemUnlockAllowedByCarrier_cb _hidl_cb) { |
| 85 | LOG(VERBOSE) << "Running OemLock::isOemUnlockAllowedByCarrier"; |
| 86 | ScopedEseConnection ese{mEse}; |
| 87 | ese.init(); |
| 88 | // Open SE session for applet |
| 89 | EseBootSession session; |
| 90 | ese_boot_session_init(&session); |
| 91 | EseAppResult res = ese_boot_session_open(mEse.ese_interface(), &session); |
| 92 | if (res != ESE_APP_RESULT_OK) { |
| 93 | LOG(ERROR) << "Failed to open a boot session: " << res; |
| 94 | _hidl_cb(OemLockStatus::FAILED, false); |
| 95 | return Void(); |
| 96 | } |
| 97 | std::vector<uint8_t> data; |
| 98 | data.resize(1024); |
| 99 | uint16_t actualData = 0; |
| 100 | res = ese_boot_lock_xget(&session, kEseBootLockIdCarrier, |
| 101 | &data[0], data.size(), |
| 102 | &actualData); |
| 103 | if (res != ESE_APP_RESULT_OK || actualData == 0) { |
| 104 | LOG(ERROR) << "Failed to get lock state: " << res; |
| 105 | } |
| 106 | |
| 107 | // Try and close the session without perturbing our result value. |
| 108 | if (ese_boot_session_close(&session) != ESE_APP_RESULT_OK) { |
| 109 | LOG(WARNING) << "Failed to close boot session"; |
| 110 | } |
| 111 | |
| 112 | if (res != ESE_APP_RESULT_OK) { |
| 113 | // Fail closed. |
| 114 | _hidl_cb(OemLockStatus::FAILED, false); |
| 115 | return Void(); |
| 116 | } |
| 117 | // if data[0] == 1, lock == true, so allowed == false. |
| 118 | _hidl_cb(OemLockStatus::OK, data[0] != 0 ? false : true); |
| 119 | return Void(); |
| 120 | } |
| 121 | |
| 122 | Return<OemLockStatus> OemLock::setOemUnlockAllowedByDevice(bool allowed) { |
| 123 | LOG(INFO) << "Running OemLock::setOemUnlockAllowedByDevice: " << allowed; |
| 124 | ScopedEseConnection ese{mEse}; |
| 125 | ese.init(); |
| 126 | // "allowed" == unlocked == 0. |
| 127 | uint8_t lock_byte = allowed ? 0 : 1; |
| 128 | |
| 129 | // Open SE session for applet |
| 130 | EseBootSession session; |
| 131 | ese_boot_session_init(&session); |
| 132 | EseAppResult res = ese_boot_session_open(mEse.ese_interface(), &session); |
| 133 | if (res != ESE_APP_RESULT_OK) { |
| 134 | LOG(ERROR) << "Failed to open a boot session: " << res; |
| 135 | return OemLockStatus::FAILED; |
| 136 | } |
| 137 | res = ese_boot_lock_set(&session, kEseBootLockIdDevice, lock_byte); |
| 138 | if (res != ESE_APP_RESULT_OK) { |
| 139 | LOG(ERROR) << "Failed to change device lock state (allowed=" |
| 140 | << allowed << "): " << res; |
| 141 | } |
| 142 | |
| 143 | // Try and close the session without perturbing our result value. |
| 144 | if (ese_boot_session_close(&session) != ESE_APP_RESULT_OK) { |
| 145 | LOG(WARNING) << "Failed to close boot session"; |
| 146 | } |
| 147 | |
| 148 | if (res != ESE_APP_RESULT_OK) { |
| 149 | return OemLockStatus::FAILED; |
| 150 | } |
| 151 | return OemLockStatus::OK; |
| 152 | } |
| 153 | |
| 154 | Return<void> OemLock::isOemUnlockAllowedByDevice(isOemUnlockAllowedByDevice_cb _hidl_cb) { |
| 155 | LOG(VERBOSE) << "Running OemLock::isOemUnlockAllowedByDevice"; |
| 156 | ScopedEseConnection ese{mEse}; |
| 157 | ese.init(); |
| 158 | // Open SE session for applet |
| 159 | EseBootSession session; |
| 160 | ese_boot_session_init(&session); |
| 161 | EseAppResult res = ese_boot_session_open(mEse.ese_interface(), &session); |
| 162 | if (res != ESE_APP_RESULT_OK) { |
| 163 | LOG(ERROR) << "Failed to open a boot session: " << res; |
| 164 | _hidl_cb(OemLockStatus::FAILED, false); |
| 165 | return Void(); |
| 166 | } |
| 167 | uint8_t lock_byte = 0; |
| 168 | res = ese_boot_lock_get(&session, kEseBootLockIdDevice, &lock_byte); |
| 169 | if (res != ESE_APP_RESULT_OK) { |
| 170 | LOG(ERROR) << "Failed to get device lock state: " << res; |
| 171 | } |
| 172 | |
| 173 | // Try and close the session without perturbing our result value. |
| 174 | if (ese_boot_session_close(&session) != ESE_APP_RESULT_OK) { |
| 175 | LOG(WARNING) << "Failed to close boot session"; |
| 176 | } |
| 177 | |
| 178 | if (res != ESE_APP_RESULT_OK) { |
| 179 | // Fail closed. |
| 180 | _hidl_cb(OemLockStatus::FAILED, false); |
| 181 | return Void(); |
| 182 | } |
| 183 | // if data[0] == 1, lock == true, so allowed == false. |
| 184 | _hidl_cb(OemLockStatus::OK, lock_byte != 0 ? false : true); |
| 185 | return Void(); |
| 186 | } |
| 187 | |
| 188 | } // namespace esed |
| 189 | } // namespace android |