Home | History | Annotate | Download | only in keystore
      1 /*
      2  **
      3  ** Copyright 2016, The Android Open Source Project
      4  **
      5  ** Licensed under the Apache License, Version 2.0 (the "License");
      6  ** you may not use this file except in compliance with the License.
      7  ** You may obtain a copy of the License at
      8  **
      9  **     http://www.apache.org/licenses/LICENSE-2.0
     10  **
     11  ** Unless required by applicable law or agreed to in writing, software
     12  ** distributed under the License is distributed on an "AS IS" BASIS,
     13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  ** See the License for the specific language governing permissions and
     15  ** limitations under the License.
     16  */
     17 
     18 #define LOG_TAG "android.hardware.keymaster (at) 3.0-impl"
     19 
     20 #include "legacy_keymaster_device_wrapper.h"
     21 
     22 #include <cutils/log.h>
     23 
     24 #include <hardware/keymaster2.h>
     25 #include <hardware/keymaster_defs.h>
     26 #include <keymaster/keymaster_configuration.h>
     27 #include <keymaster/soft_keymaster_device.h>
     28 
     29 namespace android {
     30 namespace keystore {
     31 
     32 using ::keymaster::SoftKeymasterDevice;
     33 
     34 LegacyKeymasterDeviceWrapper::LegacyKeymasterDeviceWrapper(keymaster2_device_t* dev)
     35     : keymaster_device_(dev) {}
     36 
     37 LegacyKeymasterDeviceWrapper::~LegacyKeymasterDeviceWrapper() {
     38     if (keymaster_device_) keymaster_device_->common.close(&keymaster_device_->common);
     39 }
     40 
     41 static inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
     42     return keymaster_tag_get_type(tag);
     43 }
     44 
     45 /**
     46  * legacy_enum_conversion converts enums from hidl to keymaster and back. Currently, this is just a
     47  * cast to make the compiler happy. One of two thigs should happen though:
     48  * TODO The keymaster enums should become aliases for the hidl generated enums so that we have a
     49  *      single point of truth. Then this cast function can go away.
     50  */
     51 inline static keymaster_tag_t legacy_enum_conversion(const Tag value) {
     52     return keymaster_tag_t(value);
     53 }
     54 inline static Tag legacy_enum_conversion(const keymaster_tag_t value) {
     55     return Tag(value);
     56 }
     57 inline static keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
     58     return keymaster_purpose_t(value);
     59 }
     60 inline static keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
     61     return keymaster_key_format_t(value);
     62 }
     63 inline static ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
     64     return ErrorCode(value);
     65 }
     66 
     67 class KmParamSet : public keymaster_key_param_set_t {
     68   public:
     69     KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
     70         params = new keymaster_key_param_t[keyParams.size()];
     71         length = keyParams.size();
     72         for (size_t i = 0; i < keyParams.size(); ++i) {
     73             auto tag = legacy_enum_conversion(keyParams[i].tag);
     74             switch (typeFromTag(tag)) {
     75             case KM_ENUM:
     76             case KM_ENUM_REP:
     77                 params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
     78                 break;
     79             case KM_UINT:
     80             case KM_UINT_REP:
     81                 params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
     82                 break;
     83             case KM_ULONG:
     84             case KM_ULONG_REP:
     85                 params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
     86                 break;
     87             case KM_DATE:
     88                 params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
     89                 break;
     90             case KM_BOOL:
     91                 if (keyParams[i].f.boolValue)
     92                     params[i] = keymaster_param_bool(tag);
     93                 else
     94                     params[i].tag = KM_TAG_INVALID;
     95                 break;
     96             case KM_BIGNUM:
     97             case KM_BYTES:
     98                 params[i] =
     99                     keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size());
    100                 break;
    101             case KM_INVALID:
    102             default:
    103                 params[i].tag = KM_TAG_INVALID;
    104                 /* just skip */
    105                 break;
    106             }
    107         }
    108     }
    109     KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} {
    110         other.length = 0;
    111         other.params = nullptr;
    112     }
    113     KmParamSet(const KmParamSet&) = delete;
    114     ~KmParamSet() { delete[] params; }
    115 };
    116 
    117 inline static KmParamSet hidlParams2KmParamSet(const hidl_vec<KeyParameter>& params) {
    118     return KmParamSet(params);
    119 }
    120 
    121 inline static keymaster_blob_t hidlVec2KmBlob(const hidl_vec<uint8_t>& blob) {
    122     /* hidl unmarshals funny pointers if the the blob is empty */
    123     if (blob.size()) return {&blob[0], blob.size()};
    124     return {};
    125 }
    126 
    127 inline static keymaster_key_blob_t hidlVec2KmKeyBlob(const hidl_vec<uint8_t>& blob) {
    128     /* hidl unmarshals funny pointers if the the blob is empty */
    129     if (blob.size()) return {&blob[0], blob.size()};
    130     return {};
    131 }
    132 
    133 inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_key_blob_t& blob) {
    134     hidl_vec<uint8_t> result;
    135     result.setToExternal(const_cast<unsigned char*>(blob.key_material), blob.key_material_size);
    136     return result;
    137 }
    138 inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_blob_t& blob) {
    139     hidl_vec<uint8_t> result;
    140     result.setToExternal(const_cast<unsigned char*>(blob.data), blob.data_length);
    141     return result;
    142 }
    143 
    144 inline static hidl_vec<hidl_vec<uint8_t>>
    145 kmCertChain2Hidl(const keymaster_cert_chain_t* cert_chain) {
    146     hidl_vec<hidl_vec<uint8_t>> result;
    147     if (!cert_chain || cert_chain->entry_count == 0 || !cert_chain->entries) return result;
    148 
    149     result.resize(cert_chain->entry_count);
    150     for (size_t i = 0; i < cert_chain->entry_count; ++i) {
    151         auto& entry = cert_chain->entries[i];
    152         result[i] = kmBlob2hidlVec(entry);
    153     }
    154 
    155     return result;
    156 }
    157 
    158 static inline hidl_vec<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
    159     hidl_vec<KeyParameter> result;
    160     if (set.length == 0 || set.params == nullptr) return result;
    161 
    162     result.resize(set.length);
    163     keymaster_key_param_t* params = set.params;
    164     for (size_t i = 0; i < set.length; ++i) {
    165         auto tag = params[i].tag;
    166         result[i].tag = legacy_enum_conversion(tag);
    167         switch (typeFromTag(tag)) {
    168         case KM_ENUM:
    169         case KM_ENUM_REP:
    170             result[i].f.integer = params[i].enumerated;
    171             break;
    172         case KM_UINT:
    173         case KM_UINT_REP:
    174             result[i].f.integer = params[i].integer;
    175             break;
    176         case KM_ULONG:
    177         case KM_ULONG_REP:
    178             result[i].f.longInteger = params[i].long_integer;
    179             break;
    180         case KM_DATE:
    181             result[i].f.dateTime = params[i].date_time;
    182             break;
    183         case KM_BOOL:
    184             result[i].f.boolValue = params[i].boolean;
    185             break;
    186         case KM_BIGNUM:
    187         case KM_BYTES:
    188             result[i].blob.setToExternal(const_cast<unsigned char*>(params[i].blob.data),
    189                                          params[i].blob.data_length);
    190             break;
    191         case KM_INVALID:
    192         default:
    193             params[i].tag = KM_TAG_INVALID;
    194             /* just skip */
    195             break;
    196         }
    197     }
    198     return result;
    199 }
    200 
    201 // Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
    202 Return<void> LegacyKeymasterDeviceWrapper::getHardwareFeatures(getHardwareFeatures_cb _hidl_cb) {
    203     _hidl_cb(false, false, false, false, false, "Fallback Device", "Google Android Security");
    204     return Void();
    205 }
    206 
    207 Return<ErrorCode> LegacyKeymasterDeviceWrapper::addRngEntropy(const hidl_vec<uint8_t>& data) {
    208     return legacy_enum_conversion(
    209         keymaster_device_->add_rng_entropy(keymaster_device_, &data[0], data.size()));
    210 }
    211 
    212 Return<void> LegacyKeymasterDeviceWrapper::generateKey(const hidl_vec<KeyParameter>& keyParams,
    213                                                        generateKey_cb _hidl_cb) {
    214     // result variables for the wire
    215     KeyCharacteristics resultCharacteristics;
    216     hidl_vec<uint8_t> resultKeyBlob;
    217 
    218     // result variables the backend understands
    219     keymaster_key_blob_t key_blob{nullptr, 0};
    220     keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
    221 
    222     // convert the parameter set to something our backend understands
    223     auto kmParams = hidlParams2KmParamSet(keyParams);
    224 
    225     auto rc = keymaster_device_->generate_key(keymaster_device_, &kmParams, &key_blob,
    226                                               &key_characteristics);
    227 
    228     if (rc == KM_ERROR_OK) {
    229         // on success convert the result to wire format
    230         resultKeyBlob = kmBlob2hidlVec(key_blob);
    231         resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
    232         resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
    233     }
    234 
    235     // send results off to the client
    236     _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
    237 
    238     // free buffers that we are responsible for
    239     if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
    240     keymaster_free_characteristics(&key_characteristics);
    241 
    242     return Void();
    243 }
    244 
    245 Return<void> LegacyKeymasterDeviceWrapper::getKeyCharacteristics(
    246     const hidl_vec<uint8_t>& keyBlob, const hidl_vec<uint8_t>& clientId,
    247     const hidl_vec<uint8_t>& appData, getKeyCharacteristics_cb _hidl_cb) {
    248     // result variables for the wire
    249     KeyCharacteristics resultCharacteristics;
    250 
    251     // result variables the backend understands
    252     keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
    253 
    254     auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
    255     auto kmClientId = hidlVec2KmBlob(clientId);
    256     auto kmAppData = hidlVec2KmBlob(appData);
    257 
    258     auto rc = keymaster_device_->get_key_characteristics(
    259         keymaster_device_, keyBlob.size() ? &kmKeyBlob : nullptr,
    260         clientId.size() ? &kmClientId : nullptr, appData.size() ? &kmAppData : nullptr,
    261         &key_characteristics);
    262 
    263     if (rc == KM_ERROR_OK) {
    264         resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
    265         resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
    266     }
    267 
    268     _hidl_cb(legacy_enum_conversion(rc), resultCharacteristics);
    269 
    270     keymaster_free_characteristics(&key_characteristics);
    271 
    272     return Void();
    273 }
    274 
    275 Return<void> LegacyKeymasterDeviceWrapper::importKey(const hidl_vec<KeyParameter>& params,
    276                                                      KeyFormat keyFormat,
    277                                                      const hidl_vec<uint8_t>& keyData,
    278                                                      importKey_cb _hidl_cb) {
    279     // result variables for the wire
    280     KeyCharacteristics resultCharacteristics;
    281     hidl_vec<uint8_t> resultKeyBlob;
    282 
    283     // result variables the backend understands
    284     keymaster_key_blob_t key_blob{nullptr, 0};
    285     keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
    286 
    287     auto kmParams = hidlParams2KmParamSet(params);
    288     auto kmKeyData = hidlVec2KmBlob(keyData);
    289 
    290     auto rc = keymaster_device_->import_key(keymaster_device_, &kmParams,
    291                                             legacy_enum_conversion(keyFormat), &kmKeyData,
    292                                             &key_blob, &key_characteristics);
    293 
    294     if (rc == KM_ERROR_OK) {
    295         // on success convert the result to wire format
    296         resultKeyBlob = kmBlob2hidlVec(key_blob);
    297         resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
    298         resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
    299     }
    300 
    301     _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
    302 
    303     // free buffers that we are responsible for
    304     if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
    305     keymaster_free_characteristics(&key_characteristics);
    306 
    307     return Void();
    308 }
    309 
    310 Return<void> LegacyKeymasterDeviceWrapper::exportKey(KeyFormat exportFormat,
    311                                                      const hidl_vec<uint8_t>& keyBlob,
    312                                                      const hidl_vec<uint8_t>& clientId,
    313                                                      const hidl_vec<uint8_t>& appData,
    314                                                      exportKey_cb _hidl_cb) {
    315 
    316     // result variables for the wire
    317     hidl_vec<uint8_t> resultKeyBlob;
    318 
    319     // result variables the backend understands
    320     keymaster_blob_t out_blob = {};
    321 
    322     auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
    323     auto kmClientId = hidlVec2KmBlob(clientId);
    324     auto kmAppData = hidlVec2KmBlob(appData);
    325 
    326     auto rc = keymaster_device_->export_key(keymaster_device_, legacy_enum_conversion(exportFormat),
    327                                             keyBlob.size() ? &kmKeyBlob : nullptr,
    328                                             clientId.size() ? &kmClientId : nullptr,
    329                                             appData.size() ? &kmAppData : nullptr, &out_blob);
    330 
    331     if (rc == KM_ERROR_OK) {
    332         // on success convert the result to wire format
    333         // (Can we assume that key_blob is {nullptr, 0} or a valid buffer description?)
    334         resultKeyBlob = kmBlob2hidlVec(out_blob);
    335     }
    336 
    337     _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
    338 
    339     // free buffers that we are responsible for
    340     if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
    341 
    342     return Void();
    343 }
    344 
    345 Return<void> LegacyKeymasterDeviceWrapper::attestKey(const hidl_vec<uint8_t>& keyToAttest,
    346                                                      const hidl_vec<KeyParameter>& attestParams,
    347                                                      attestKey_cb _hidl_cb) {
    348 
    349     hidl_vec<hidl_vec<uint8_t>> resultCertChain;
    350 
    351     for (size_t i = 0; i < attestParams.size(); ++i) {
    352         switch (attestParams[i].tag) {
    353             case Tag::ATTESTATION_ID_BRAND:
    354             case Tag::ATTESTATION_ID_DEVICE:
    355             case Tag::ATTESTATION_ID_PRODUCT:
    356             case Tag::ATTESTATION_ID_SERIAL:
    357             case Tag::ATTESTATION_ID_IMEI:
    358             case Tag::ATTESTATION_ID_MEID:
    359             case Tag::ATTESTATION_ID_MANUFACTURER:
    360             case Tag::ATTESTATION_ID_MODEL:
    361                 // Device id attestation may only be supported if the device is able to permanently
    362                 // destroy its knowledge of the ids. This device is unable to do this, so it must
    363                 // never perform any device id attestation.
    364                 _hidl_cb(ErrorCode::CANNOT_ATTEST_IDS, resultCertChain);
    365                 return Void();
    366             default:
    367                 break;
    368         }
    369     }
    370 
    371     keymaster_cert_chain_t cert_chain = {};
    372 
    373     auto kmKeyToAttest = hidlVec2KmKeyBlob(keyToAttest);
    374     auto kmAttestParams = hidlParams2KmParamSet(attestParams);
    375 
    376     auto rc = keymaster_device_->attest_key(keymaster_device_, &kmKeyToAttest, &kmAttestParams,
    377                                             &cert_chain);
    378 
    379     if (rc == KM_ERROR_OK) {
    380         resultCertChain = kmCertChain2Hidl(&cert_chain);
    381     }
    382 
    383     _hidl_cb(legacy_enum_conversion(rc), resultCertChain);
    384 
    385     keymaster_free_cert_chain(&cert_chain);
    386 
    387     return Void();
    388 }
    389 
    390 Return<void> LegacyKeymasterDeviceWrapper::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
    391                                                       const hidl_vec<KeyParameter>& upgradeParams,
    392                                                       upgradeKey_cb _hidl_cb) {
    393 
    394     // result variables for the wire
    395     hidl_vec<uint8_t> resultKeyBlob;
    396 
    397     // result variables the backend understands
    398     keymaster_key_blob_t key_blob = {};
    399 
    400     auto kmKeyBlobToUpgrade = hidlVec2KmKeyBlob(keyBlobToUpgrade);
    401     auto kmUpgradeParams = hidlParams2KmParamSet(upgradeParams);
    402 
    403     auto rc = keymaster_device_->upgrade_key(keymaster_device_, &kmKeyBlobToUpgrade,
    404                                              &kmUpgradeParams, &key_blob);
    405 
    406     if (rc == KM_ERROR_OK) {
    407         // on success convert the result to wire format
    408         resultKeyBlob = kmBlob2hidlVec(key_blob);
    409     }
    410 
    411     _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
    412 
    413     if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
    414 
    415     return Void();
    416 }
    417 
    418 Return<ErrorCode> LegacyKeymasterDeviceWrapper::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
    419     auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
    420     return legacy_enum_conversion(keymaster_device_->delete_key(keymaster_device_, &kmKeyBlob));
    421 }
    422 
    423 Return<ErrorCode> LegacyKeymasterDeviceWrapper::deleteAllKeys() {
    424     return legacy_enum_conversion(keymaster_device_->delete_all_keys(keymaster_device_));
    425 }
    426 
    427 Return<ErrorCode> LegacyKeymasterDeviceWrapper::destroyAttestationIds() {
    428     return ErrorCode::UNIMPLEMENTED;
    429 }
    430 
    431 Return<void> LegacyKeymasterDeviceWrapper::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
    432                                                  const hidl_vec<KeyParameter>& inParams,
    433                                                  begin_cb _hidl_cb) {
    434 
    435     // result variables for the wire
    436     hidl_vec<KeyParameter> resultParams;
    437     uint64_t resultOpHandle = 0;
    438 
    439     // result variables the backend understands
    440     keymaster_key_param_set_t out_params{nullptr, 0};
    441     keymaster_operation_handle_t& operation_handle = resultOpHandle;
    442 
    443     auto kmKey = hidlVec2KmKeyBlob(key);
    444     auto kmInParams = hidlParams2KmParamSet(inParams);
    445 
    446     auto rc = keymaster_device_->begin(keymaster_device_, legacy_enum_conversion(purpose), &kmKey,
    447                                        &kmInParams, &out_params, &operation_handle);
    448 
    449     if (rc == KM_ERROR_OK) resultParams = kmParamSet2Hidl(out_params);
    450 
    451     _hidl_cb(legacy_enum_conversion(rc), resultParams, resultOpHandle);
    452 
    453     keymaster_free_param_set(&out_params);
    454 
    455     return Void();
    456 }
    457 
    458 Return<void> LegacyKeymasterDeviceWrapper::update(uint64_t operationHandle,
    459                                                   const hidl_vec<KeyParameter>& inParams,
    460                                                   const hidl_vec<uint8_t>& input,
    461                                                   update_cb _hidl_cb) {
    462     // result variables for the wire
    463     uint32_t resultConsumed = 0;
    464     hidl_vec<KeyParameter> resultParams;
    465     hidl_vec<uint8_t> resultBlob;
    466 
    467     // result variables the backend understands
    468     size_t consumed = 0;
    469     keymaster_key_param_set_t out_params = {};
    470     keymaster_blob_t out_blob = {};
    471 
    472     auto kmInParams = hidlParams2KmParamSet(inParams);
    473     auto kmInput = hidlVec2KmBlob(input);
    474 
    475     auto rc = keymaster_device_->update(keymaster_device_, operationHandle, &kmInParams, &kmInput,
    476                                         &consumed, &out_params, &out_blob);
    477 
    478     if (rc == KM_ERROR_OK) {
    479         resultConsumed = consumed;
    480         resultParams = kmParamSet2Hidl(out_params);
    481         resultBlob = kmBlob2hidlVec(out_blob);
    482     }
    483 
    484     _hidl_cb(legacy_enum_conversion(rc), resultConsumed, resultParams, resultBlob);
    485 
    486     keymaster_free_param_set(&out_params);
    487     if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
    488 
    489     return Void();
    490 }
    491 
    492 Return<void> LegacyKeymasterDeviceWrapper::finish(uint64_t operationHandle,
    493                                                   const hidl_vec<KeyParameter>& inParams,
    494                                                   const hidl_vec<uint8_t>& input,
    495                                                   const hidl_vec<uint8_t>& signature,
    496                                                   finish_cb _hidl_cb) {
    497     // result variables for the wire
    498     hidl_vec<KeyParameter> resultParams;
    499     hidl_vec<uint8_t> resultBlob;
    500 
    501     // result variables the backend understands
    502     keymaster_key_param_set_t out_params = {};
    503     keymaster_blob_t out_blob = {};
    504 
    505     auto kmInParams = hidlParams2KmParamSet(inParams);
    506     auto kmInput = hidlVec2KmBlob(input);
    507     auto kmSignature = hidlVec2KmBlob(signature);
    508 
    509     auto rc = keymaster_device_->finish(keymaster_device_, operationHandle, &kmInParams, &kmInput,
    510                                         &kmSignature, &out_params, &out_blob);
    511 
    512     if (rc == KM_ERROR_OK) {
    513         resultParams = kmParamSet2Hidl(out_params);
    514         resultBlob = kmBlob2hidlVec(out_blob);
    515     }
    516 
    517     _hidl_cb(legacy_enum_conversion(rc), resultParams, resultBlob);
    518 
    519     keymaster_free_param_set(&out_params);
    520     if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
    521 
    522     return Void();
    523 }
    524 
    525 Return<ErrorCode> LegacyKeymasterDeviceWrapper::abort(uint64_t operationHandle) {
    526     return legacy_enum_conversion(keymaster_device_->abort(keymaster_device_, operationHandle));
    527 }
    528 
    529 sp<IKeymasterDevice> makeSoftwareKeymasterDevice() {
    530     keymaster2_device_t* dev = nullptr;
    531     dev = (new SoftKeymasterDevice)->keymaster2_device();
    532 
    533     auto kmrc = ::keymaster::ConfigureDevice(dev);
    534     if (kmrc != KM_ERROR_OK) {
    535         dev->common.close(&dev->common);
    536         return nullptr;
    537     }
    538 
    539     return new LegacyKeymasterDeviceWrapper(dev);
    540 }
    541 
    542 }  // namespace keystore
    543 }  // namespace android
    544