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