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 "keymaster/authorization_set.h"
     23 #include "keymaster/keymaster_tags.h"
     24 #include "keystore/keystore_client_impl.h"
     25 
     26 using base::CommandLine;
     27 using keymaster::AuthorizationSet;
     28 using keymaster::AuthorizationSetBuilder;
     29 using keystore::KeystoreClient;
     30 
     31 namespace {
     32 
     33 struct TestCase {
     34     std::string name;
     35     bool required_for_brillo_pts;
     36     AuthorizationSet parameters;
     37 };
     38 
     39 void PrintUsageAndExit() {
     40     printf("Usage: keystore_client_v2 <command> [options]\n");
     41     printf("Commands: brillo-platform-test [--prefix=<test_name_prefix>]\n"
     42            "          list-brillo-tests\n"
     43            "          add-entropy --input=<entropy>\n"
     44            "          generate --name=<key_name>\n"
     45            "          get-chars --name=<key_name>\n"
     46            "          export --name=<key_name>\n"
     47            "          delete --name=<key_name>\n"
     48            "          delete-all\n"
     49            "          exists --name=<key_name>\n"
     50            "          list [--prefix=<key_name_prefix>]\n"
     51            "          sign-verify --name=<key_name>\n"
     52            "          [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n");
     53     exit(1);
     54 }
     55 
     56 std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
     57     return std::unique_ptr<KeystoreClient>(new keystore::KeystoreClientImpl);
     58 }
     59 
     60 #ifndef KEYMASTER_NAME_TAGS
     61 #erro KEYMASTER_NAME_TAGS must be defined
     62 #endif
     63 
     64 void PrintTags(const AuthorizationSet& parameters) {
     65     const keymaster_key_param_t* iter = nullptr;
     66     for (iter = parameters.begin(); iter != parameters.end(); ++iter) {
     67         printf("  %s\n", keymaster::StringifyTag(iter->tag));
     68     }
     69 }
     70 
     71 void PrintKeyCharacteristics(const AuthorizationSet& hardware_enforced_characteristics,
     72                              const AuthorizationSet& software_enforced_characteristics) {
     73     printf("Hardware:\n");
     74     PrintTags(hardware_enforced_characteristics);
     75     printf("Software:\n");
     76     PrintTags(software_enforced_characteristics);
     77 }
     78 
     79 bool TestKey(const std::string& name, bool required, const AuthorizationSet& parameters) {
     80     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
     81     AuthorizationSet hardware_enforced_characteristics;
     82     AuthorizationSet software_enforced_characteristics;
     83     int32_t result = keystore->generateKey("tmp", parameters, &hardware_enforced_characteristics,
     84                                            &software_enforced_characteristics);
     85     if (result != KM_ERROR_OK) {
     86         LOG(ERROR) << "Failed to generate key: " << result;
     87         printf("%s Result: ABORT\n", name.c_str());
     88         return false;
     89     }
     90     result = keystore->deleteKey("tmp");
     91     if (result != KM_ERROR_OK) {
     92         LOG(ERROR) << "Failed to delete key: " << result;
     93         printf("%s Result: ABORT\n", name.c_str());
     94         return false;
     95     }
     96     printf("===============================================================\n");
     97     printf("%s Key Characteristics:\n", name.c_str());
     98     PrintKeyCharacteristics(hardware_enforced_characteristics, software_enforced_characteristics);
     99     bool hardware_backed = (hardware_enforced_characteristics.size() > 0);
    100     if (software_enforced_characteristics.GetTagCount(KM_TAG_PURPOSE) > 0 ||
    101         software_enforced_characteristics.GetTagCount(KM_TAG_ALGORITHM) > 0 ||
    102         software_enforced_characteristics.GetTagCount(KM_TAG_KEY_SIZE) > 0 ||
    103         software_enforced_characteristics.GetTagCount(KM_TAG_RSA_PUBLIC_EXPONENT) > 0 ||
    104         software_enforced_characteristics.GetTagCount(KM_TAG_DIGEST) > 0 ||
    105         software_enforced_characteristics.GetTagCount(KM_TAG_PADDING) > 0 ||
    106         software_enforced_characteristics.GetTagCount(KM_TAG_BLOCK_MODE) > 0) {
    107         VLOG(1) << "Hardware-backed key but required characteristics enforced in software.";
    108         hardware_backed = false;
    109     }
    110     const char kBoldRedFail[] = "\033[1;31mFAIL\033[0m";
    111     const char kBoldGreenPass[] = "\033[1;32mPASS\033[0m";
    112     const char kBoldYellowWarn[] = "\033[1;33mWARN\033[0m";
    113     printf("[%s] %s\n",
    114            hardware_backed ? kBoldGreenPass : (required ? kBoldRedFail : kBoldYellowWarn),
    115            name.c_str());
    116 
    117     return (hardware_backed || !required);
    118 }
    119 
    120 AuthorizationSet GetRSASignParameters(uint32_t key_size, bool sha256_only) {
    121     AuthorizationSetBuilder parameters;
    122     parameters.RsaSigningKey(key_size, 65537)
    123         .Digest(KM_DIGEST_SHA_2_256)
    124         .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)
    125         .Padding(KM_PAD_RSA_PSS)
    126         .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
    127     if (!sha256_only) {
    128         parameters.Digest(KM_DIGEST_SHA_2_224)
    129             .Digest(KM_DIGEST_SHA_2_384)
    130             .Digest(KM_DIGEST_SHA_2_512);
    131     }
    132     return parameters.build();
    133 }
    134 
    135 AuthorizationSet GetRSAEncryptParameters(uint32_t key_size) {
    136     AuthorizationSetBuilder parameters;
    137     parameters.RsaEncryptionKey(key_size, 65537)
    138         .Padding(KM_PAD_RSA_PKCS1_1_5_ENCRYPT)
    139         .Padding(KM_PAD_RSA_OAEP)
    140         .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
    141     return parameters.build();
    142 }
    143 
    144 AuthorizationSet GetECDSAParameters(uint32_t key_size, bool sha256_only) {
    145     AuthorizationSetBuilder parameters;
    146     parameters.EcdsaSigningKey(key_size)
    147         .Digest(KM_DIGEST_SHA_2_256)
    148         .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
    149     if (!sha256_only) {
    150         parameters.Digest(KM_DIGEST_SHA_2_224)
    151             .Digest(KM_DIGEST_SHA_2_384)
    152             .Digest(KM_DIGEST_SHA_2_512);
    153     }
    154     return parameters.build();
    155 }
    156 
    157 AuthorizationSet GetAESParameters(uint32_t key_size, bool with_gcm_mode) {
    158     AuthorizationSetBuilder parameters;
    159     parameters.AesEncryptionKey(key_size).Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
    160     if (with_gcm_mode) {
    161         parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_GCM)
    162             .Authorization(keymaster::TAG_MIN_MAC_LENGTH, 128);
    163     } else {
    164         parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_ECB);
    165         parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CBC);
    166         parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CTR);
    167     }
    168     return parameters.build();
    169 }
    170 
    171 AuthorizationSet GetHMACParameters(uint32_t key_size, keymaster_digest_t digest) {
    172     AuthorizationSetBuilder parameters;
    173     parameters.HmacKey(key_size)
    174         .Digest(digest)
    175         .Authorization(keymaster::TAG_MIN_MAC_LENGTH, 224)
    176         .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
    177     return parameters.build();
    178 }
    179 
    180 std::vector<TestCase> GetTestCases() {
    181     TestCase test_cases[] = {
    182         {"RSA-2048 Sign", true, GetRSASignParameters(2048, true)},
    183         {"RSA-2048 Sign (more digests)", false, GetRSASignParameters(2048, false)},
    184         {"RSA-3072 Sign", false, GetRSASignParameters(3072, false)},
    185         {"RSA-4096 Sign", false, GetRSASignParameters(4096, false)},
    186         {"RSA-2048 Encrypt", true, GetRSAEncryptParameters(2048)},
    187         {"RSA-3072 Encrypt", false, GetRSAEncryptParameters(3072)},
    188         {"RSA-4096 Encrypt", false, GetRSAEncryptParameters(4096)},
    189         {"ECDSA-P256 Sign", true, GetECDSAParameters(256, true)},
    190         {"ECDSA-P256 Sign (more digests)", false, GetECDSAParameters(256, false)},
    191         {"ECDSA-P224 Sign", false, GetECDSAParameters(224, false)},
    192         {"ECDSA-P384 Sign", false, GetECDSAParameters(384, false)},
    193         {"ECDSA-P521 Sign", false, GetECDSAParameters(521, false)},
    194         {"AES-128", true, GetAESParameters(128, false)},
    195         {"AES-256", true, GetAESParameters(256, false)},
    196         {"AES-128-GCM", false, GetAESParameters(128, true)},
    197         {"AES-256-GCM", false, GetAESParameters(256, true)},
    198         {"HMAC-SHA256-16", true, GetHMACParameters(16, KM_DIGEST_SHA_2_256)},
    199         {"HMAC-SHA256-32", true, GetHMACParameters(32, KM_DIGEST_SHA_2_256)},
    200         {"HMAC-SHA256-64", false, GetHMACParameters(64, KM_DIGEST_SHA_2_256)},
    201         {"HMAC-SHA224-32", false, GetHMACParameters(32, KM_DIGEST_SHA_2_224)},
    202         {"HMAC-SHA384-32", false, GetHMACParameters(32, KM_DIGEST_SHA_2_384)},
    203         {"HMAC-SHA512-32", false, GetHMACParameters(32, KM_DIGEST_SHA_2_512)},
    204     };
    205     return std::vector<TestCase>(&test_cases[0], &test_cases[arraysize(test_cases)]);
    206 }
    207 
    208 int BrilloPlatformTest(const std::string& prefix) {
    209     int test_count = 0;
    210     int fail_count = 0;
    211     std::vector<TestCase> test_cases = GetTestCases();
    212     for (const auto& test_case : test_cases) {
    213         if (!prefix.empty() && test_case.name.find(prefix) != 0) {
    214             continue;
    215         }
    216         ++test_count;
    217         if (!TestKey(test_case.name, test_case.required_for_brillo_pts, test_case.parameters)) {
    218             VLOG(1) << "Test failed: " << test_case.name;
    219             ++fail_count;
    220         }
    221     }
    222     return fail_count;
    223 }
    224 
    225 int ListTestCases() {
    226     const char kBoldGreenRequired[] = "\033[1;32mREQUIRED\033[0m";
    227     const char kBoldYellowRecommended[] = "\033[1;33mRECOMMENDED\033[0m";
    228     std::vector<TestCase> test_cases = GetTestCases();
    229     for (const auto& test_case : test_cases) {
    230         printf("%s : %s\n", test_case.name.c_str(),
    231                test_case.required_for_brillo_pts ? kBoldGreenRequired : kBoldYellowRecommended);
    232     }
    233     return 0;
    234 }
    235 
    236 std::string ReadFile(const std::string& filename) {
    237     std::string content;
    238     base::FilePath path(filename);
    239     if (!base::ReadFileToString(path, &content)) {
    240         printf("Failed to read file: %s\n", filename.c_str());
    241         exit(1);
    242     }
    243     return content;
    244 }
    245 
    246 void WriteFile(const std::string& filename, const std::string& content) {
    247     base::FilePath path(filename);
    248     int size = content.size();
    249     if (base::WriteFile(path, content.data(), size) != size) {
    250         printf("Failed to write file: %s\n", filename.c_str());
    251         exit(1);
    252     }
    253 }
    254 
    255 int AddEntropy(const std::string& input) {
    256     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    257     int32_t result = keystore->addRandomNumberGeneratorEntropy(input);
    258     printf("AddEntropy: %d\n", result);
    259     return result;
    260 }
    261 
    262 int GenerateKey(const std::string& name) {
    263     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    264     AuthorizationSetBuilder params;
    265     params.RsaSigningKey(2048, 65537)
    266         .Digest(KM_DIGEST_SHA_2_224)
    267         .Digest(KM_DIGEST_SHA_2_256)
    268         .Digest(KM_DIGEST_SHA_2_384)
    269         .Digest(KM_DIGEST_SHA_2_512)
    270         .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)
    271         .Padding(KM_PAD_RSA_PSS)
    272         .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
    273     AuthorizationSet hardware_enforced_characteristics;
    274     AuthorizationSet software_enforced_characteristics;
    275     int32_t result = keystore->generateKey(name, params.build(), &hardware_enforced_characteristics,
    276                                            &software_enforced_characteristics);
    277     printf("GenerateKey: %d\n", result);
    278     if (result == KM_ERROR_OK) {
    279         PrintKeyCharacteristics(hardware_enforced_characteristics,
    280                                 software_enforced_characteristics);
    281     }
    282     return result;
    283 }
    284 
    285 int GetCharacteristics(const std::string& name) {
    286     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    287     AuthorizationSet hardware_enforced_characteristics;
    288     AuthorizationSet software_enforced_characteristics;
    289     int32_t result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
    290                                                      &software_enforced_characteristics);
    291     printf("GetCharacteristics: %d\n", result);
    292     if (result == KM_ERROR_OK) {
    293         PrintKeyCharacteristics(hardware_enforced_characteristics,
    294                                 software_enforced_characteristics);
    295     }
    296     return result;
    297 }
    298 
    299 int ExportKey(const std::string& name) {
    300     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    301     std::string data;
    302     int32_t result = keystore->exportKey(KM_KEY_FORMAT_X509, name, &data);
    303     printf("ExportKey: %d (%zu)\n", result, data.size());
    304     return result;
    305 }
    306 
    307 int DeleteKey(const std::string& name) {
    308     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    309     int32_t result = keystore->deleteKey(name);
    310     printf("DeleteKey: %d\n", result);
    311     return result;
    312 }
    313 
    314 int DeleteAllKeys() {
    315     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    316     int32_t result = keystore->deleteAllKeys();
    317     printf("DeleteAllKeys: %d\n", result);
    318     return result;
    319 }
    320 
    321 int DoesKeyExist(const std::string& name) {
    322     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    323     printf("DoesKeyExist: %s\n", keystore->doesKeyExist(name) ? "yes" : "no");
    324     return 0;
    325 }
    326 
    327 int List(const std::string& prefix) {
    328     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    329     std::vector<std::string> key_list;
    330     if (!keystore->listKeys(prefix, &key_list)) {
    331         printf("ListKeys failed.\n");
    332         return 1;
    333     }
    334     printf("Keys:\n");
    335     for (const auto& key_name : key_list) {
    336         printf("  %s\n", key_name.c_str());
    337     }
    338     return 0;
    339 }
    340 
    341 int SignAndVerify(const std::string& name) {
    342     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    343     AuthorizationSetBuilder sign_params;
    344     sign_params.Padding(KM_PAD_RSA_PKCS1_1_5_SIGN);
    345     sign_params.Digest(KM_DIGEST_SHA_2_256);
    346     AuthorizationSet output_params;
    347     keymaster_operation_handle_t handle;
    348     int32_t result = keystore->beginOperation(KM_PURPOSE_SIGN, name, sign_params.build(),
    349                                               &output_params, &handle);
    350     if (result != KM_ERROR_OK) {
    351         printf("Sign: BeginOperation failed: %d\n", result);
    352         return result;
    353     }
    354     AuthorizationSet empty_params;
    355     size_t num_input_bytes_consumed;
    356     std::string output_data;
    357     result = keystore->updateOperation(handle, empty_params, "data_to_sign",
    358                                        &num_input_bytes_consumed, &output_params, &output_data);
    359     if (result != KM_ERROR_OK) {
    360         printf("Sign: UpdateOperation failed: %d\n", result);
    361         return result;
    362     }
    363     result = keystore->finishOperation(handle, empty_params, std::string() /*signature_to_verify*/,
    364                                        &output_params, &output_data);
    365     if (result != KM_ERROR_OK) {
    366         printf("Sign: FinishOperation failed: %d\n", result);
    367         return result;
    368     }
    369     printf("Sign: %zu bytes.\n", output_data.size());
    370     // We have a signature, now verify it.
    371     std::string signature_to_verify = output_data;
    372     output_data.clear();
    373     result = keystore->beginOperation(KM_PURPOSE_VERIFY, name, sign_params.build(), &output_params,
    374                                       &handle);
    375     if (result != KM_ERROR_OK) {
    376         printf("Verify: BeginOperation failed: %d\n", result);
    377         return result;
    378     }
    379     result = keystore->updateOperation(handle, empty_params, "data_to_sign",
    380                                        &num_input_bytes_consumed, &output_params, &output_data);
    381     if (result != KM_ERROR_OK) {
    382         printf("Verify: UpdateOperation failed: %d\n", result);
    383         return result;
    384     }
    385     result = keystore->finishOperation(handle, empty_params, signature_to_verify, &output_params,
    386                                        &output_data);
    387     if (result == KM_ERROR_VERIFICATION_FAILED) {
    388         printf("Verify: Failed to verify signature.\n");
    389         return result;
    390     }
    391     if (result != KM_ERROR_OK) {
    392         printf("Verify: FinishOperation failed: %d\n", result);
    393         return result;
    394     }
    395     printf("Verify: OK\n");
    396     return 0;
    397 }
    398 
    399 int Encrypt(const std::string& key_name, const std::string& input_filename,
    400             const std::string& output_filename) {
    401     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    402     std::string input = ReadFile(input_filename);
    403     std::string output;
    404     if (!keystore->encryptWithAuthentication(key_name, input, &output)) {
    405         printf("EncryptWithAuthentication failed.\n");
    406         return 1;
    407     }
    408     WriteFile(output_filename, output);
    409     return 0;
    410 }
    411 
    412 int Decrypt(const std::string& key_name, const std::string& input_filename,
    413             const std::string& output_filename) {
    414     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
    415     std::string input = ReadFile(input_filename);
    416     std::string output;
    417     if (!keystore->decryptWithAuthentication(key_name, input, &output)) {
    418         printf("DecryptWithAuthentication failed.\n");
    419         return 1;
    420     }
    421     WriteFile(output_filename, output);
    422     return 0;
    423 }
    424 
    425 }  // namespace
    426 
    427 int main(int argc, char** argv) {
    428     CommandLine::Init(argc, argv);
    429     CommandLine* command_line = CommandLine::ForCurrentProcess();
    430     CommandLine::StringVector args = command_line->GetArgs();
    431     if (args.empty()) {
    432         PrintUsageAndExit();
    433     }
    434     if (args[0] == "brillo-platform-test") {
    435         return BrilloPlatformTest(command_line->GetSwitchValueASCII("prefix"));
    436     } else if (args[0] == "list-brillo-tests") {
    437         return ListTestCases();
    438     } else if (args[0] == "add-entropy") {
    439         return AddEntropy(command_line->GetSwitchValueASCII("input"));
    440     } else if (args[0] == "generate") {
    441         return GenerateKey(command_line->GetSwitchValueASCII("name"));
    442     } else if (args[0] == "get-chars") {
    443         return GetCharacteristics(command_line->GetSwitchValueASCII("name"));
    444     } else if (args[0] == "export") {
    445         return ExportKey(command_line->GetSwitchValueASCII("name"));
    446     } else if (args[0] == "delete") {
    447         return DeleteKey(command_line->GetSwitchValueASCII("name"));
    448     } else if (args[0] == "delete-all") {
    449         return DeleteAllKeys();
    450     } else if (args[0] == "exists") {
    451         return DoesKeyExist(command_line->GetSwitchValueASCII("name"));
    452     } else if (args[0] == "list") {
    453         return List(command_line->GetSwitchValueASCII("prefix"));
    454     } else if (args[0] == "sign-verify") {
    455         return SignAndVerify(command_line->GetSwitchValueASCII("name"));
    456     } else if (args[0] == "encrypt") {
    457         return Encrypt(command_line->GetSwitchValueASCII("name"),
    458                        command_line->GetSwitchValueASCII("in"),
    459                        command_line->GetSwitchValueASCII("out"));
    460     } else if (args[0] == "decrypt") {
    461         return Decrypt(command_line->GetSwitchValueASCII("name"),
    462                        command_line->GetSwitchValueASCII("in"),
    463                        command_line->GetSwitchValueASCII("out"));
    464     } else {
    465         PrintUsageAndExit();
    466     }
    467     return 0;
    468 }
    469