• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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