/* * 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 "Weaver.h" #include #include #include #include #include "ScopedEseConnection.h" namespace android { namespace esed { // libhidl using ::android::hardware::Void; // HAL using ::android::hardware::weaver::V1_0::WeaverConfig; using ::android::hardware::weaver::V1_0::WeaverReadResponse; using ::android::hardware::weaver::V1_0::WeaverReadStatus; // Methods from ::android::hardware::weaver::V1_0::IWeaver follow. Return Weaver::getConfig(getConfig_cb _hidl_cb) { LOG(VERBOSE) << "Running Weaver::getNumSlots"; // Open SE session for applet ScopedEseConnection ese{mEse}; ese.init(); EseWeaverSession ws; ese_weaver_session_init(&ws); EseAppResult res = ese_weaver_session_open(mEse.ese_interface(), &ws); if (EseAppResultValue(res) == ESE_APP_RESULT_ERROR_OS) { switch (EseAppResultAppValue(res)) { case 0x6999: // SW_APPLET_SELECT_FAILED case 0x6A82: // SW_FILE_NOT_FOUND // No applet means no Weaver storage. Report no slots to prompt // fallback to software mode. _hidl_cb(WeaverStatus::OK, WeaverConfig{0, 0, 0}); return Void(); } } else if (res != ESE_APP_RESULT_OK) { // Transient error _hidl_cb(WeaverStatus::FAILED, WeaverConfig{}); return Void(); } // Call the applet uint32_t numSlots; if (ese_weaver_get_num_slots(&ws, &numSlots) != ESE_APP_RESULT_OK) { _hidl_cb(WeaverStatus::FAILED, WeaverConfig{}); return Void(); } // Try and close the session if (ese_weaver_session_close(&ws) != ESE_APP_RESULT_OK) { LOG(WARNING) << "Failed to close Weaver session"; } _hidl_cb(WeaverStatus::OK, WeaverConfig{numSlots, kEseWeaverKeySize, kEseWeaverValueSize}); return Void(); } Return Weaver::write(uint32_t slotId, const hidl_vec& key, const hidl_vec& value) { LOG(INFO) << "Running Weaver::write on slot " << slotId; ScopedEseConnection ese{mEse}; ese.init(); // Validate the key and value sizes if (key.size() != kEseWeaverKeySize) { LOG(ERROR) << "Key size must be " << kEseWeaverKeySize << ", not" << key.size() << " bytes"; return WeaverStatus::FAILED; } if (value.size() != kEseWeaverValueSize) { LOG(ERROR) << "Value size must be " << kEseWeaverValueSize << ", not" << value.size() << " bytes"; return WeaverStatus::FAILED; } // Open SE session for applet EseWeaverSession ws; ese_weaver_session_init(&ws); if (ese_weaver_session_open(mEse.ese_interface(), &ws) != ESE_APP_RESULT_OK) { return WeaverStatus::FAILED; } // Call the applet if (ese_weaver_write(&ws, slotId, key.data(), value.data()) != ESE_APP_RESULT_OK) { return WeaverStatus::FAILED; } // Try and close the session if (ese_weaver_session_close(&ws) != ESE_APP_RESULT_OK) { LOG(WARNING) << "Failed to close Weaver session"; } return WeaverStatus::OK; } Return Weaver::read(uint32_t slotId, const hidl_vec& key, read_cb _hidl_cb) { LOG(VERBOSE) << "Running Weaver::read on slot " << slotId; // Validate the key size if (key.size() != kEseWeaverKeySize) { LOG(ERROR) << "Key size must be " << kEseWeaverKeySize << ", not" << key.size() << " bytes"; _hidl_cb(WeaverReadStatus::FAILED, WeaverReadResponse{}); return Void(); } // Open SE session for applet ScopedEseConnection ese{mEse}; ese.init(); EseWeaverSession ws; ese_weaver_session_init(&ws); if (ese_weaver_session_open(mEse.ese_interface(), &ws) != ESE_APP_RESULT_OK) { _hidl_cb(WeaverReadStatus::FAILED, WeaverReadResponse{}); return Void(); } // Call the applet hidl_vec value; value.resize(kEseWeaverValueSize); uint32_t timeout; const int res = ese_weaver_read(&ws, slotId, key.data(), value.data(), &timeout); WeaverReadStatus status; switch (res) { case ESE_APP_RESULT_OK: status = WeaverReadStatus::OK; timeout = 0; break; case ESE_WEAVER_READ_WRONG_KEY: status = WeaverReadStatus::INCORRECT_KEY; value.resize(0); break; case ESE_WEAVER_READ_TIMEOUT: status = WeaverReadStatus::THROTTLE; value.resize(0); break; default: status = WeaverReadStatus::FAILED; timeout = 0; value.resize(0); break; } // Try and close the session if (ese_weaver_session_close(&ws) != ESE_APP_RESULT_OK) { LOG(WARNING) << "Failed to close Weaver session"; } _hidl_cb(status, WeaverReadResponse{timeout, value}); return Void(); } } // namespace esed } // namespace android