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 <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.
getConfig(getConfig_cb _hidl_cb)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
write(uint32_t slotId,const hidl_vec<uint8_t> & key,const hidl_vec<uint8_t> & value)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
read(uint32_t slotId,const hidl_vec<uint8_t> & key,read_cb _hidl_cb)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