Home | History | Annotate | Download | only in esed
      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