Home | History | Annotate | Download | only in keystore
      1 // Copyright 2015 The Android Open Source Project
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include <cstdio>
     16 #include <memory>
     17 #include <string>
     18 #include <vector>
     19 
     20 #include <base/command_line.h>
     21 #include <base/files/file_util.h>
     22 #include <base/strings/string_number_conversions.h>
     23 #include <base/strings/string_split.h>
     24 #include <base/strings/string_util.h>
     25 #include <base/strings/utf_string_conversions.h>
     26 #include <base/threading/platform_thread.h>
     27 #include <keystore/keymaster_types.h>
     28 #include <keystore/keystore_client_impl.h>
     29 
     30 #include <android/hardware/confirmationui/1.0/types.h>
     31 #include <android/security/BnConfirmationPromptCallback.h>
     32 #include <android/security/IKeystoreService.h>
     33 
     34 #include <binder/IPCThreadState.h>
     35 #include <binder/IServiceManager.h>
     36 
     37 //#include <keystore/keystore.h>
     38 
     39 using base::CommandLine;
     40 using keystore::KeystoreClient;
     41 
     42 using android::sp;
     43 using android::String16;
     44 using android::security::IKeystoreService;
     45 using base::CommandLine;
     46 using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
     47 
     48 namespace {
     49 using namespace keystore;
     50 
     51 struct TestCase {
     52     std::string name;
     53     bool required_for_brillo_pts;
     54     AuthorizationSet parameters;
     55 };
     56 
     57 void PrintUsageAndExit() {
     58     printf("Usage: keystore_client_v2 <command> [options]\n");
     59     printf("Commands: brillo-platform-test [--prefix=<test_name_prefix>] [--test_for_0_3]\n"
     60            "          list-brillo-tests\n"
     61            "          add-entropy --input=<entropy> [--seclevel=software|strongbox|tee(default)]\n"
     62            "          generate --name=<key_name> [--seclevel=software|strongbox|tee(default)]\n"
     63            "          get-chars --name=<key_name>\n"
     64            "          export --name=<key_name>\n"
     65            "          delete --name=<key_name>\n"
     66            "          delete-all\n"
     67            "          exists --name=<key_name>\n"
     68            "          list [--prefix=<key_name_prefix>]\n"
     69            "          sign-verify --name=<key_name>\n"
     70            "          [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n"
     71            "                       [--seclevel=software|strongbox|tee(default)]\n"
     72            "          confirmation --prompt_text=<PromptText> --extra_data=<hex>\n"
     73            "                       --locale=<locale> [--ui_options=<list_of_ints>]\n"
     74            "                       --cancel_after=<seconds>\n");
     75     exit(1);
     76 }
     77 
     78 std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
     79     return std::unique_ptr<KeystoreClient>(
     80         static_cast<KeystoreClient*>(new keystore::KeystoreClientImpl));
     81 }
     82 
     83 void PrintTags(const AuthorizationSet& parameters) {
     84     for (auto iter = parameters.begin(); iter != parameters.end(); ++iter) {
     85         auto tag_str = toString(iter->tag);
     86         printf("  %s\n", tag_str.c_str());
     87     }
     88 }
     89 
     90 void PrintKeyCharacteristics(const AuthorizationSet& hardware_enforced_characteristics,
     91                              const AuthorizationSet& software_enforced_characteristics) {
     92     printf("Hardware:\n");
     93     PrintTags(hardware_enforced_characteristics);
     94     printf("Software:\n");
     95     PrintTags(software_enforced_characteristics);
     96 }
     97 
     98 bool TestKey(const std::string& name, bool required, const AuthorizationSet& parameters) {
     99     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    100     AuthorizationSet hardware_enforced_characteristics;
    101     AuthorizationSet software_enforced_characteristics;
    102     auto result =
    103         keystore->generateKey("tmp", parameters, 0 /*flags*/, &hardware_enforced_characteristics,
    104                               &software_enforced_characteristics);
    105     const char kBoldRedAbort[] = "\033[1;31mABORT\033[0m";
    106     if (!result.isOk()) {
    107         LOG(ERROR) << "Failed to generate key: " << result;
    108         printf("[%s] %s\n", kBoldRedAbort, name.c_str());
    109         return false;
    110     }
    111     result = keystore->deleteKey("tmp");
    112     if (!result.isOk()) {
    113         LOG(ERROR) << "Failed to delete key: " << result;
    114         printf("[%s] %s\n", kBoldRedAbort, name.c_str());
    115         return false;
    116     }
    117     printf("===============================================================\n");
    118     printf("%s Key Characteristics:\n", name.c_str());
    119     PrintKeyCharacteristics(hardware_enforced_characteristics, software_enforced_characteristics);
    120     bool hardware_backed = (hardware_enforced_characteristics.size() > 0);
    121     if (software_enforced_characteristics.GetTagCount(TAG_ALGORITHM) > 0 ||
    122         software_enforced_characteristics.GetTagCount(TAG_KEY_SIZE) > 0 ||
    123         software_enforced_characteristics.GetTagCount(TAG_RSA_PUBLIC_EXPONENT) > 0) {
    124         VLOG(1) << "Hardware-backed key but required characteristics enforced in software.";
    125         hardware_backed = false;
    126     }
    127     const char kBoldRedFail[] = "\033[1;31mFAIL\033[0m";
    128     const char kBoldGreenPass[] = "\033[1;32mPASS\033[0m";
    129     const char kBoldYellowWarn[] = "\033[1;33mWARN\033[0m";
    130     printf("[%s] %s\n",
    131            hardware_backed ? kBoldGreenPass : (required ? kBoldRedFail : kBoldYellowWarn),
    132            name.c_str());
    133 
    134     return (hardware_backed || !required);
    135 }
    136 
    137 AuthorizationSet GetRSASignParameters(uint32_t key_size, bool sha256_only) {
    138     AuthorizationSetBuilder parameters;
    139     parameters.RsaSigningKey(key_size, 65537)
    140         .Digest(Digest::SHA_2_256)
    141         .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
    142         .Padding(PaddingMode::RSA_PSS)
    143         .Authorization(TAG_NO_AUTH_REQUIRED);
    144     if (!sha256_only) {
    145         parameters.Digest(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512);
    146     }
    147     return parameters;
    148 }
    149 
    150 AuthorizationSet GetRSAEncryptParameters(uint32_t key_size) {
    151     AuthorizationSetBuilder parameters;
    152     parameters.RsaEncryptionKey(key_size, 65537)
    153         .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT)
    154         .Padding(PaddingMode::RSA_OAEP)
    155         .Authorization(TAG_NO_AUTH_REQUIRED);
    156     return parameters;
    157 }
    158 
    159 AuthorizationSet GetECDSAParameters(uint32_t key_size, bool sha256_only) {
    160     AuthorizationSetBuilder parameters;
    161     parameters.EcdsaSigningKey(key_size)
    162         .Digest(Digest::SHA_2_256)
    163         .Authorization(TAG_NO_AUTH_REQUIRED);
    164     if (!sha256_only) {
    165         parameters.Digest(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512);
    166     }
    167     return parameters;
    168 }
    169 
    170 AuthorizationSet GetAESParameters(uint32_t key_size, bool with_gcm_mode) {
    171     AuthorizationSetBuilder parameters;
    172     parameters.AesEncryptionKey(key_size).Authorization(TAG_NO_AUTH_REQUIRED);
    173     if (with_gcm_mode) {
    174         parameters.Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
    175             .Authorization(TAG_MIN_MAC_LENGTH, 128);
    176     } else {
    177         parameters.Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
    178         parameters.Authorization(TAG_BLOCK_MODE, BlockMode::CBC);
    179         parameters.Authorization(TAG_BLOCK_MODE, BlockMode::CTR);
    180         parameters.Padding(PaddingMode::NONE);
    181     }
    182     return parameters;
    183 }
    184 
    185 AuthorizationSet GetHMACParameters(uint32_t key_size, Digest digest) {
    186     AuthorizationSetBuilder parameters;
    187     parameters.HmacKey(key_size)
    188         .Digest(digest)
    189         .Authorization(TAG_MIN_MAC_LENGTH, 224)
    190         .Authorization(TAG_NO_AUTH_REQUIRED);
    191     return parameters;
    192 }
    193 
    194 std::vector<TestCase> GetTestCases() {
    195     TestCase test_cases[] = {
    196         {"RSA-2048 Sign", true, GetRSASignParameters(2048, true)},
    197         {"RSA-2048 Sign (more digests)", false, GetRSASignParameters(2048, false)},
    198         {"RSA-3072 Sign", false, GetRSASignParameters(3072, false)},
    199         {"RSA-4096 Sign", false, GetRSASignParameters(4096, false)},
    200         {"RSA-2048 Encrypt", true, GetRSAEncryptParameters(2048)},
    201         {"RSA-3072 Encrypt", false, GetRSAEncryptParameters(3072)},
    202         {"RSA-4096 Encrypt", false, GetRSAEncryptParameters(4096)},
    203         {"ECDSA-P256 Sign", true, GetECDSAParameters(256, true)},
    204         {"ECDSA-P256 Sign (more digests)", false, GetECDSAParameters(256, false)},
    205         {"ECDSA-P224 Sign", false, GetECDSAParameters(224, false)},
    206         {"ECDSA-P384 Sign", false, GetECDSAParameters(384, false)},
    207         {"ECDSA-P521 Sign", false, GetECDSAParameters(521, false)},
    208         {"AES-128", true, GetAESParameters(128, false)},
    209         {"AES-256", true, GetAESParameters(256, false)},
    210         {"AES-128-GCM", false, GetAESParameters(128, true)},
    211         {"AES-256-GCM", false, GetAESParameters(256, true)},
    212         {"HMAC-SHA256-16", true, GetHMACParameters(16, Digest::SHA_2_256)},
    213         {"HMAC-SHA256-32", true, GetHMACParameters(32, Digest::SHA_2_256)},
    214         {"HMAC-SHA256-64", false, GetHMACParameters(64, Digest::SHA_2_256)},
    215         {"HMAC-SHA224-32", false, GetHMACParameters(32, Digest::SHA_2_224)},
    216         {"HMAC-SHA384-32", false, GetHMACParameters(32, Digest::SHA_2_384)},
    217         {"HMAC-SHA512-32", false, GetHMACParameters(32, Digest::SHA_2_512)},
    218     };
    219     return std::vector<TestCase>(&test_cases[0], &test_cases[arraysize(test_cases)]);
    220 }
    221 
    222 int BrilloPlatformTest(const std::string& prefix, bool test_for_0_3) {
    223     const char kBoldYellowWarning[] = "\033[1;33mWARNING\033[0m";
    224     if (test_for_0_3) {
    225         printf("%s: Testing for keymaster v0.3. "
    226                "This does not meet Brillo requirements.\n",
    227                kBoldYellowWarning);
    228     }
    229     int test_count = 0;
    230     int fail_count = 0;
    231     std::vector<TestCase> test_cases = GetTestCases();
    232     for (const auto& test_case : test_cases) {
    233         if (!prefix.empty() &&
    234             !base::StartsWith(test_case.name, prefix, base::CompareCase::SENSITIVE)) {
    235             continue;
    236         }
    237         if (test_for_0_3 &&
    238             (base::StartsWith(test_case.name, "AES", base::CompareCase::SENSITIVE) ||
    239              base::StartsWith(test_case.name, "HMAC", base::CompareCase::SENSITIVE))) {
    240             continue;
    241         }
    242         ++test_count;
    243         if (!TestKey(test_case.name, test_case.required_for_brillo_pts, test_case.parameters)) {
    244             VLOG(1) << "Test failed: " << test_case.name;
    245             ++fail_count;
    246         }
    247     }
    248     return fail_count;
    249 }
    250 
    251 int ListTestCases() {
    252     const char kBoldGreenRequired[] = "\033[1;32mREQUIRED\033[0m";
    253     const char kBoldYellowRecommended[] = "\033[1;33mRECOMMENDED\033[0m";
    254     std::vector<TestCase> test_cases = GetTestCases();
    255     for (const auto& test_case : test_cases) {
    256         printf("%s : %s\n", test_case.name.c_str(),
    257                test_case.required_for_brillo_pts ? kBoldGreenRequired : kBoldYellowRecommended);
    258     }
    259     return 0;
    260 }
    261 
    262 std::string ReadFile(const std::string& filename) {
    263     std::string content;
    264     base::FilePath path(filename);
    265     if (!base::ReadFileToString(path, &content)) {
    266         printf("Failed to read file: %s\n", filename.c_str());
    267         exit(1);
    268     }
    269     return content;
    270 }
    271 
    272 void WriteFile(const std::string& filename, const std::string& content) {
    273     base::FilePath path(filename);
    274     int size = content.size();
    275     if (base::WriteFile(path, content.data(), size) != size) {
    276         printf("Failed to write file: %s\n", filename.c_str());
    277         exit(1);
    278     }
    279 }
    280 
    281 int AddEntropy(const std::string& input, int32_t flags) {
    282     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    283     int32_t result = keystore->addRandomNumberGeneratorEntropy(input, flags);
    284     printf("AddEntropy: %d\n", result);
    285     return result;
    286 }
    287 
    288 int GenerateKey(const std::string& name, int32_t flags) {
    289     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    290     AuthorizationSetBuilder params;
    291     params.RsaSigningKey(2048, 65537)
    292         .Digest(Digest::SHA_2_224)
    293         .Digest(Digest::SHA_2_256)
    294         .Digest(Digest::SHA_2_384)
    295         .Digest(Digest::SHA_2_512)
    296         .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
    297         .Padding(PaddingMode::RSA_PSS)
    298         .Authorization(TAG_NO_AUTH_REQUIRED);
    299     AuthorizationSet hardware_enforced_characteristics;
    300     AuthorizationSet software_enforced_characteristics;
    301     auto result = keystore->generateKey(name, params, flags, &hardware_enforced_characteristics,
    302                                         &software_enforced_characteristics);
    303     printf("GenerateKey: %d\n", int32_t(result));
    304     if (result.isOk()) {
    305         PrintKeyCharacteristics(hardware_enforced_characteristics,
    306                                 software_enforced_characteristics);
    307     }
    308     return result;
    309 }
    310 
    311 int GetCharacteristics(const std::string& name) {
    312     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    313     AuthorizationSet hardware_enforced_characteristics;
    314     AuthorizationSet software_enforced_characteristics;
    315     auto result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
    316                                                   &software_enforced_characteristics);
    317     printf("GetCharacteristics: %d\n", int32_t(result));
    318     if (result.isOk()) {
    319         PrintKeyCharacteristics(hardware_enforced_characteristics,
    320                                 software_enforced_characteristics);
    321     }
    322     return result;
    323 }
    324 
    325 int ExportKey(const std::string& name) {
    326     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    327     std::string data;
    328     int32_t result = keystore->exportKey(KeyFormat::X509, name, &data);
    329     printf("ExportKey: %d (%zu)\n", result, data.size());
    330     return result;
    331 }
    332 
    333 int DeleteKey(const std::string& name) {
    334     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    335     int32_t result = keystore->deleteKey(name);
    336     printf("DeleteKey: %d\n", result);
    337     return result;
    338 }
    339 
    340 int DeleteAllKeys() {
    341     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    342     int32_t result = keystore->deleteAllKeys();
    343     printf("DeleteAllKeys: %d\n", result);
    344     return result;
    345 }
    346 
    347 int DoesKeyExist(const std::string& name) {
    348     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    349     printf("DoesKeyExist: %s\n", keystore->doesKeyExist(name) ? "yes" : "no");
    350     return 0;
    351 }
    352 
    353 int List(const std::string& prefix) {
    354     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    355     std::vector<std::string> key_list;
    356     if (!keystore->listKeys(prefix, &key_list)) {
    357         printf("ListKeys failed.\n");
    358         return 1;
    359     }
    360     printf("Keys:\n");
    361     for (const auto& key_name : key_list) {
    362         printf("  %s\n", key_name.c_str());
    363     }
    364     return 0;
    365 }
    366 
    367 int SignAndVerify(const std::string& name) {
    368     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    369     AuthorizationSetBuilder sign_params;
    370     sign_params.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN);
    371     sign_params.Digest(Digest::SHA_2_256);
    372     AuthorizationSet output_params;
    373     uint64_t handle;
    374     auto result =
    375         keystore->beginOperation(KeyPurpose::SIGN, name, sign_params, &output_params, &handle);
    376     if (!result.isOk()) {
    377         printf("Sign: BeginOperation failed: %d\n", int32_t(result));
    378         return result;
    379     }
    380     AuthorizationSet empty_params;
    381     size_t num_input_bytes_consumed;
    382     std::string output_data;
    383     result = keystore->updateOperation(handle, empty_params, "data_to_sign",
    384                                        &num_input_bytes_consumed, &output_params, &output_data);
    385     if (!result.isOk()) {
    386         printf("Sign: UpdateOperation failed: %d\n", int32_t(result));
    387         return result;
    388     }
    389     result = keystore->finishOperation(handle, empty_params, std::string() /*signature_to_verify*/,
    390                                        &output_params, &output_data);
    391     if (!result.isOk()) {
    392         printf("Sign: FinishOperation failed: %d\n", int32_t(result));
    393         return result;
    394     }
    395     printf("Sign: %zu bytes.\n", output_data.size());
    396     // We have a signature, now verify it.
    397     std::string signature_to_verify = output_data;
    398     output_data.clear();
    399     result =
    400         keystore->beginOperation(KeyPurpose::VERIFY, name, sign_params, &output_params, &handle);
    401     if (!result.isOk()) {
    402         printf("Verify: BeginOperation failed: %d\n", int32_t(result));
    403         return result;
    404     }
    405     result = keystore->updateOperation(handle, empty_params, "data_to_sign",
    406                                        &num_input_bytes_consumed, &output_params, &output_data);
    407     if (!result.isOk()) {
    408         printf("Verify: UpdateOperation failed: %d\n", int32_t(result));
    409         return result;
    410     }
    411     result = keystore->finishOperation(handle, empty_params, signature_to_verify, &output_params,
    412                                        &output_data);
    413     if (result == ErrorCode::VERIFICATION_FAILED) {
    414         printf("Verify: Failed to verify signature.\n");
    415         return result;
    416     }
    417     if (!result.isOk()) {
    418         printf("Verify: FinishOperation failed: %d\n", int32_t(result));
    419         return result;
    420     }
    421     printf("Verify: OK\n");
    422     return 0;
    423 }
    424 
    425 int Encrypt(const std::string& key_name, const std::string& input_filename,
    426             const std::string& output_filename, int32_t flags) {
    427     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    428     std::string input = ReadFile(input_filename);
    429     std::string output;
    430     if (!keystore->encryptWithAuthentication(key_name, input, flags, &output)) {
    431         printf("EncryptWithAuthentication failed.\n");
    432         return 1;
    433     }
    434     WriteFile(output_filename, output);
    435     return 0;
    436 }
    437 
    438 int Decrypt(const std::string& key_name, const std::string& input_filename,
    439             const std::string& output_filename) {
    440     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    441     std::string input = ReadFile(input_filename);
    442     std::string output;
    443     if (!keystore->decryptWithAuthentication(key_name, input, &output)) {
    444         printf("DecryptWithAuthentication failed.\n");
    445         return 1;
    446     }
    447     WriteFile(output_filename, output);
    448     return 0;
    449 }
    450 
    451 uint32_t securityLevelOption2Flags(const CommandLine& cmd) {
    452     if (cmd.HasSwitch("seclevel")) {
    453         auto str = cmd.GetSwitchValueASCII("seclevel");
    454         if (str == "strongbox") {
    455             return KEYSTORE_FLAG_STRONGBOX;
    456         } else if (str == "software") {
    457             return KEYSTORE_FLAG_FALLBACK;
    458         }
    459     }
    460     return KEYSTORE_FLAG_NONE;
    461 }
    462 
    463 class ConfirmationListener : public android::security::BnConfirmationPromptCallback {
    464   public:
    465     ConfirmationListener() {}
    466 
    467     virtual ::android::binder::Status
    468     onConfirmationPromptCompleted(int32_t result,
    469                                   const ::std::vector<uint8_t>& dataThatWasConfirmed) override {
    470         ConfirmationResponseCode responseCode = static_cast<ConfirmationResponseCode>(result);
    471         printf("Confirmation prompt completed\n"
    472                "responseCode = %d\n",
    473                responseCode);
    474         printf("dataThatWasConfirmed[%zd] = {", dataThatWasConfirmed.size());
    475         size_t newLineCountDown = 16;
    476         bool hasPrinted = false;
    477         for (uint8_t element : dataThatWasConfirmed) {
    478             if (hasPrinted) {
    479                 printf(", ");
    480             }
    481             if (newLineCountDown == 0) {
    482                 printf("\n  ");
    483                 newLineCountDown = 32;
    484             }
    485             printf("0x%02x", element);
    486             hasPrinted = true;
    487         }
    488         printf("}\n");
    489         exit(0);
    490     }
    491 };
    492 
    493 int Confirmation(const std::string& promptText, const std::string& extraDataHex,
    494                  const std::string& locale, const std::string& uiOptionsStr,
    495                  const std::string& cancelAfter) {
    496     sp<android::IServiceManager> sm = android::defaultServiceManager();
    497     sp<android::IBinder> binder = sm->getService(String16("android.security.keystore"));
    498     sp<IKeystoreService> service = android::interface_cast<IKeystoreService>(binder);
    499     if (service == NULL) {
    500         printf("error: could not connect to keystore service.\n");
    501         return 1;
    502     }
    503 
    504     if (promptText.size() == 0) {
    505         printf("The --prompt_text parameter cannot be empty.\n");
    506         return 1;
    507     }
    508 
    509     std::vector<uint8_t> extraData;
    510     if (!base::HexStringToBytes(extraDataHex, &extraData)) {
    511         printf("The --extra_data parameter does not appear to be valid hexadecimal.\n");
    512         return 1;
    513     }
    514 
    515     std::vector<std::string> pieces =
    516         base::SplitString(uiOptionsStr, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    517     int uiOptionsAsFlags = 0;
    518     for (auto& p : pieces) {
    519         int value;
    520         if (!base::StringToInt(p, &value)) {
    521             printf("Error parsing %s in --ui_options parameter as a number.\n", p.c_str());
    522             return 1;
    523         }
    524         uiOptionsAsFlags |= (1 << value);
    525     }
    526 
    527     double cancelAfterValue = 0.0;
    528 
    529     if (cancelAfter.size() > 0 && !base::StringToDouble(cancelAfter, &cancelAfterValue)) {
    530         printf("Error parsing %s in --cancel_after parameter as a double.\n", cancelAfter.c_str());
    531         return 1;
    532     }
    533 
    534     String16 promptText16(promptText.data(), promptText.size());
    535     String16 locale16(locale.data(), locale.size());
    536 
    537     sp<ConfirmationListener> listener = new ConfirmationListener();
    538 
    539     int32_t aidl_return;
    540     android::binder::Status status = service->presentConfirmationPrompt(
    541         listener, promptText16, extraData, locale16, uiOptionsAsFlags, &aidl_return);
    542     if (!status.isOk()) {
    543         printf("Presenting confirmation prompt failed with binder status '%s'.\n",
    544                status.toString8().c_str());
    545         return 1;
    546     }
    547     ConfirmationResponseCode responseCode = static_cast<ConfirmationResponseCode>(aidl_return);
    548     if (responseCode != ConfirmationResponseCode::OK) {
    549         printf("Presenting confirmation prompt failed with response code %d.\n", responseCode);
    550         return 1;
    551     }
    552 
    553     if (cancelAfterValue > 0.0) {
    554         printf("Sleeping %.1f seconds before canceling prompt...\n", cancelAfterValue);
    555         base::PlatformThread::Sleep(base::TimeDelta::FromSecondsD(cancelAfterValue));
    556         status = service->cancelConfirmationPrompt(listener, &aidl_return);
    557         if (!status.isOk()) {
    558             printf("Canceling confirmation prompt failed with binder status '%s'.\n",
    559                    status.toString8().c_str());
    560             return 1;
    561         }
    562         responseCode = static_cast<ConfirmationResponseCode>(aidl_return);
    563         if (responseCode != ConfirmationResponseCode::OK) {
    564             printf("Canceling confirmation prompt failed with response code %d.\n", responseCode);
    565             return 1;
    566         }
    567     }
    568 
    569     printf("Waiting for prompt to complete - use Ctrl+C to abort...\n");
    570     // Use the main thread to process Binder transactions.
    571     android::IPCThreadState::self()->joinThreadPool();
    572     return 0;
    573 }
    574 
    575 }  // namespace
    576 
    577 int main(int argc, char** argv) {
    578     CommandLine::Init(argc, argv);
    579     CommandLine* command_line = CommandLine::ForCurrentProcess();
    580     CommandLine::StringVector args = command_line->GetArgs();
    581     if (args.empty()) {
    582         PrintUsageAndExit();
    583     }
    584     if (args[0] == "brillo-platform-test") {
    585         return BrilloPlatformTest(command_line->GetSwitchValueASCII("prefix"),
    586                                   command_line->HasSwitch("test_for_0_3"));
    587     } else if (args[0] == "list-brillo-tests") {
    588         return ListTestCases();
    589     } else if (args[0] == "add-entropy") {
    590         return AddEntropy(command_line->GetSwitchValueASCII("input"),
    591                           securityLevelOption2Flags(*command_line));
    592     } else if (args[0] == "generate") {
    593         return GenerateKey(command_line->GetSwitchValueASCII("name"),
    594                            securityLevelOption2Flags(*command_line));
    595     } else if (args[0] == "get-chars") {
    596         return GetCharacteristics(command_line->GetSwitchValueASCII("name"));
    597     } else if (args[0] == "export") {
    598         return ExportKey(command_line->GetSwitchValueASCII("name"));
    599     } else if (args[0] == "delete") {
    600         return DeleteKey(command_line->GetSwitchValueASCII("name"));
    601     } else if (args[0] == "delete-all") {
    602         return DeleteAllKeys();
    603     } else if (args[0] == "exists") {
    604         return DoesKeyExist(command_line->GetSwitchValueASCII("name"));
    605     } else if (args[0] == "list") {
    606         return List(command_line->GetSwitchValueASCII("prefix"));
    607     } else if (args[0] == "sign-verify") {
    608         return SignAndVerify(command_line->GetSwitchValueASCII("name"));
    609     } else if (args[0] == "encrypt") {
    610         return Encrypt(
    611             command_line->GetSwitchValueASCII("name"), command_line->GetSwitchValueASCII("in"),
    612             command_line->GetSwitchValueASCII("out"), securityLevelOption2Flags(*command_line));
    613     } else if (args[0] == "decrypt") {
    614         return Decrypt(command_line->GetSwitchValueASCII("name"),
    615                        command_line->GetSwitchValueASCII("in"),
    616                        command_line->GetSwitchValueASCII("out"));
    617     } else if (args[0] == "confirmation") {
    618         return Confirmation(command_line->GetSwitchValueNative("prompt_text"),
    619                             command_line->GetSwitchValueASCII("extra_data"),
    620                             command_line->GetSwitchValueASCII("locale"),
    621                             command_line->GetSwitchValueASCII("ui_options"),
    622                             command_line->GetSwitchValueASCII("cancel_after"));
    623     } else {
    624         PrintUsageAndExit();
    625     }
    626     return 0;
    627 }
    628