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 "Weaver.h" 18 19 #include <algorithm> 20 #include <tuple> 21 22 #include <android-base/logging.h> 23 24 #include "../apps/weaver/include/ese/app/weaver.h" 25 #include "ScopedEseConnection.h" 26 27 namespace android { 28 namespace esed { 29 30 // libhidl 31 using ::android::hardware::Void; 32 33 // HAL 34 using ::android::hardware::weaver::V1_0::WeaverConfig; 35 using ::android::hardware::weaver::V1_0::WeaverReadResponse; 36 using ::android::hardware::weaver::V1_0::WeaverReadStatus; 37 38 // Methods from ::android::hardware::weaver::V1_0::IWeaver follow. 39 Return<void> Weaver::getConfig(getConfig_cb _hidl_cb) { 40 LOG(VERBOSE) << "Running Weaver::getNumSlots"; 41 // Open SE session for applet 42 ScopedEseConnection ese{mEse}; 43 ese.init(); 44 EseWeaverSession ws; 45 ese_weaver_session_init(&ws); 46 EseAppResult res = ese_weaver_session_open(mEse.ese_interface(), &ws); 47 if (EseAppResultValue(res) == ESE_APP_RESULT_ERROR_OS) { 48 switch (EseAppResultAppValue(res)) { 49 case 0x6999: // SW_APPLET_SELECT_FAILED 50 case 0x6A82: // SW_FILE_NOT_FOUND 51 // No applet means no Weaver storage. Report no slots to prompt 52 // fallback to software mode. 53 _hidl_cb(WeaverStatus::OK, WeaverConfig{0, 0, 0}); 54 return Void(); 55 } 56 } else if (res != ESE_APP_RESULT_OK) { 57 // Transient error 58 _hidl_cb(WeaverStatus::FAILED, WeaverConfig{}); 59 return Void(); 60 } 61 62 // Call the applet 63 uint32_t numSlots; 64 if (ese_weaver_get_num_slots(&ws, &numSlots) != ESE_APP_RESULT_OK) { 65 _hidl_cb(WeaverStatus::FAILED, WeaverConfig{}); 66 return Void(); 67 } 68 69 // Try and close the session 70 if (ese_weaver_session_close(&ws) != ESE_APP_RESULT_OK) { 71 LOG(WARNING) << "Failed to close Weaver session"; 72 } 73 74 _hidl_cb(WeaverStatus::OK, WeaverConfig{numSlots, kEseWeaverKeySize, kEseWeaverValueSize}); 75 return Void(); 76 } 77 78 Return<WeaverStatus> Weaver::write(uint32_t slotId, const hidl_vec<uint8_t>& key, 79 const hidl_vec<uint8_t>& value) { 80 LOG(INFO) << "Running Weaver::write on slot " << slotId; 81 ScopedEseConnection ese{mEse}; 82 ese.init(); 83 // Validate the key and value sizes 84 if (key.size() != kEseWeaverKeySize) { 85 LOG(ERROR) << "Key size must be " << kEseWeaverKeySize << ", not" << key.size() << " bytes"; 86 return WeaverStatus::FAILED; 87 } 88 if (value.size() != kEseWeaverValueSize) { 89 LOG(ERROR) << "Value size must be " << kEseWeaverValueSize << ", not" << value.size() 90 << " bytes"; 91 return WeaverStatus::FAILED; 92 } 93 94 // Open SE session for applet 95 EseWeaverSession ws; 96 ese_weaver_session_init(&ws); 97 if (ese_weaver_session_open(mEse.ese_interface(), &ws) != ESE_APP_RESULT_OK) { 98 return WeaverStatus::FAILED; 99 } 100 101 // Call the applet 102 if (ese_weaver_write(&ws, slotId, key.data(), value.data()) != ESE_APP_RESULT_OK) { 103 return WeaverStatus::FAILED; 104 } 105 106 // Try and close the session 107 if (ese_weaver_session_close(&ws) != ESE_APP_RESULT_OK) { 108 LOG(WARNING) << "Failed to close Weaver session"; 109 } 110 111 return WeaverStatus::OK; 112 } 113 114 Return<void> Weaver::read(uint32_t slotId, const hidl_vec<uint8_t>& key, read_cb _hidl_cb) { 115 LOG(VERBOSE) << "Running Weaver::read on slot " << slotId; 116 117 // Validate the key size 118 if (key.size() != kEseWeaverKeySize) { 119 LOG(ERROR) << "Key size must be " << kEseWeaverKeySize << ", not" << key.size() << " bytes"; 120 _hidl_cb(WeaverReadStatus::FAILED, WeaverReadResponse{}); 121 return Void(); 122 } 123 124 // Open SE session for applet 125 ScopedEseConnection ese{mEse}; 126 ese.init(); 127 EseWeaverSession ws; 128 ese_weaver_session_init(&ws); 129 if (ese_weaver_session_open(mEse.ese_interface(), &ws) != ESE_APP_RESULT_OK) { 130 _hidl_cb(WeaverReadStatus::FAILED, WeaverReadResponse{}); 131 return Void(); 132 } 133 134 // Call the applet 135 hidl_vec<uint8_t> value; 136 value.resize(kEseWeaverValueSize); 137 uint32_t timeout; 138 const int res = ese_weaver_read(&ws, slotId, key.data(), value.data(), &timeout); 139 WeaverReadStatus status; 140 switch (res) { 141 case ESE_APP_RESULT_OK: 142 status = WeaverReadStatus::OK; 143 timeout = 0; 144 break; 145 case ESE_WEAVER_READ_WRONG_KEY: 146 status = WeaverReadStatus::INCORRECT_KEY; 147 value.resize(0); 148 break; 149 case ESE_WEAVER_READ_TIMEOUT: 150 status = WeaverReadStatus::THROTTLE; 151 value.resize(0); 152 break; 153 default: 154 status = WeaverReadStatus::FAILED; 155 timeout = 0; 156 value.resize(0); 157 break; 158 } 159 160 // Try and close the session 161 if (ese_weaver_session_close(&ws) != ESE_APP_RESULT_OK) { 162 LOG(WARNING) << "Failed to close Weaver session"; 163 } 164 165 _hidl_cb(status, WeaverReadResponse{timeout, value}); 166 return Void(); 167 } 168 169 } // namespace esed 170 } // namespace android 171