Darren Krahn | 69a3dbc | 2015-09-22 16:21:04 -0700 | [diff] [blame^] | 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 "keymaster/authorization_set.h" |
| 22 | #include "keystore/keystore_client_impl.h" |
| 23 | |
| 24 | using base::CommandLine; |
| 25 | using keymaster::AuthorizationSet; |
| 26 | using keymaster::AuthorizationSetBuilder; |
| 27 | using keystore::KeystoreClient; |
| 28 | |
| 29 | namespace { |
| 30 | |
| 31 | void PrintUsageAndExit() { |
| 32 | printf("Usage: keystore_client_v2 <command> [options]\n"); |
| 33 | printf("Commands: add-entropy --input=<entropy>\n" |
| 34 | " generate --name=<key_name>\n" |
| 35 | " get-chars --name=<key_name>\n" |
| 36 | " export --name=<key_name>\n" |
| 37 | " delete --name=<key_name>\n" |
| 38 | " delete-all\n" |
| 39 | " exists --name=<key_name>\n" |
| 40 | " list [--prefix=<key_name_prefix>]\n" |
| 41 | " sign-verify --name=<key_name>\n"); |
| 42 | exit(1); |
| 43 | } |
| 44 | |
| 45 | std::unique_ptr<KeystoreClient> CreateKeystoreInstance() { |
| 46 | return std::unique_ptr<KeystoreClient>(new keystore::KeystoreClientImpl); |
| 47 | } |
| 48 | |
| 49 | int AddEntropy(const std::string& input) { |
| 50 | std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); |
| 51 | int32_t result = keystore->addRandomNumberGeneratorEntropy(input); |
| 52 | printf("AddEntropy: %d\n", result); |
| 53 | return result; |
| 54 | } |
| 55 | |
| 56 | int GenerateKey(const std::string& name) { |
| 57 | std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); |
| 58 | AuthorizationSetBuilder params; |
| 59 | params.RsaSigningKey(2048, 65537) |
| 60 | .Digest(KM_DIGEST_SHA_2_224) |
| 61 | .Digest(KM_DIGEST_SHA_2_256) |
| 62 | .Digest(KM_DIGEST_SHA_2_384) |
| 63 | .Digest(KM_DIGEST_SHA_2_512) |
| 64 | .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN) |
| 65 | .Padding(KM_PAD_RSA_PSS) |
| 66 | .Authorization(keymaster::TAG_NO_AUTH_REQUIRED); |
| 67 | AuthorizationSet hardware_enforced_characteristics; |
| 68 | AuthorizationSet software_enforced_characteristics; |
| 69 | int32_t result = keystore->generateKey(name, params.build(), &hardware_enforced_characteristics, |
| 70 | &software_enforced_characteristics); |
| 71 | printf("GenerateKey: %d (%zu, %zu)\n", result, hardware_enforced_characteristics.size(), |
| 72 | software_enforced_characteristics.size()); |
| 73 | return result; |
| 74 | } |
| 75 | |
| 76 | int GetCharacteristics(const std::string& name) { |
| 77 | std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); |
| 78 | AuthorizationSet hardware_enforced_characteristics; |
| 79 | AuthorizationSet software_enforced_characteristics; |
| 80 | int32_t result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics, |
| 81 | &software_enforced_characteristics); |
| 82 | printf("GetCharacteristics: %d (%zu, %zu)\n", result, hardware_enforced_characteristics.size(), |
| 83 | software_enforced_characteristics.size()); |
| 84 | return result; |
| 85 | } |
| 86 | |
| 87 | int ExportKey(const std::string& name) { |
| 88 | std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); |
| 89 | std::string data; |
| 90 | int32_t result = keystore->exportKey(KM_KEY_FORMAT_X509, name, &data); |
| 91 | printf("ExportKey: %d (%zu)\n", result, data.size()); |
| 92 | return result; |
| 93 | } |
| 94 | |
| 95 | int DeleteKey(const std::string& name) { |
| 96 | std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); |
| 97 | int32_t result = keystore->deleteKey(name); |
| 98 | printf("DeleteKey: %d\n", result); |
| 99 | return result; |
| 100 | } |
| 101 | |
| 102 | int DeleteAllKeys() { |
| 103 | std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); |
| 104 | int32_t result = keystore->deleteAllKeys(); |
| 105 | printf("DeleteAllKeys: %d\n", result); |
| 106 | return result; |
| 107 | } |
| 108 | |
| 109 | int DoesKeyExist(const std::string& name) { |
| 110 | std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); |
| 111 | printf("DoesKeyExist: %s\n", keystore->doesKeyExist(name) ? "yes" : "no"); |
| 112 | return 0; |
| 113 | } |
| 114 | |
| 115 | int List(const std::string& prefix) { |
| 116 | std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); |
| 117 | std::vector<std::string> key_list; |
| 118 | if (!keystore->listKeys(prefix, &key_list)) { |
| 119 | printf("ListKeys failed.\n"); |
| 120 | return 1; |
| 121 | } |
| 122 | printf("Keys:\n"); |
| 123 | for (const auto& key_name : key_list) { |
| 124 | printf(" %s\n", key_name.c_str()); |
| 125 | } |
| 126 | return 0; |
| 127 | } |
| 128 | |
| 129 | int SignAndVerify(const std::string& name) { |
| 130 | std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); |
| 131 | AuthorizationSetBuilder sign_params; |
| 132 | sign_params.Padding(KM_PAD_RSA_PKCS1_1_5_SIGN); |
| 133 | sign_params.Digest(KM_DIGEST_SHA_2_256); |
| 134 | AuthorizationSet output_params; |
| 135 | keymaster_operation_handle_t handle; |
| 136 | int32_t result = keystore->beginOperation(KM_PURPOSE_SIGN, name, sign_params.build(), |
| 137 | &output_params, &handle); |
| 138 | if (result != KM_ERROR_OK) { |
| 139 | printf("Sign: BeginOperation failed: %d\n", result); |
| 140 | return result; |
| 141 | } |
| 142 | AuthorizationSet empty_params; |
| 143 | size_t num_input_bytes_consumed; |
| 144 | std::string output_data; |
| 145 | result = keystore->updateOperation(handle, empty_params, "data_to_sign", |
| 146 | &num_input_bytes_consumed, &output_params, &output_data); |
| 147 | if (result != KM_ERROR_OK) { |
| 148 | printf("Sign: UpdateOperation failed: %d\n", result); |
| 149 | return result; |
| 150 | } |
| 151 | result = keystore->finishOperation(handle, empty_params, std::string() /*signature_to_verify*/, |
| 152 | &output_params, &output_data); |
| 153 | if (result != KM_ERROR_OK) { |
| 154 | printf("Sign: FinishOperation failed: %d\n", result); |
| 155 | return result; |
| 156 | } |
| 157 | printf("Sign: %zu bytes.\n", output_data.size()); |
| 158 | // We have a signature, now verify it. |
| 159 | std::string signature_to_verify = output_data; |
| 160 | result = keystore->beginOperation(KM_PURPOSE_VERIFY, name, sign_params.build(), &output_params, |
| 161 | &handle); |
| 162 | if (result != KM_ERROR_OK) { |
| 163 | printf("Verify: BeginOperation failed: %d\n", result); |
| 164 | return result; |
| 165 | } |
| 166 | result = keystore->updateOperation(handle, empty_params, "data_to_sign", |
| 167 | &num_input_bytes_consumed, &output_params, &output_data); |
| 168 | if (result != KM_ERROR_OK) { |
| 169 | printf("Verify: UpdateOperation failed: %d\n", result); |
| 170 | return result; |
| 171 | } |
| 172 | result = keystore->finishOperation(handle, empty_params, signature_to_verify, &output_params, |
| 173 | &output_data); |
| 174 | if (result == KM_ERROR_VERIFICATION_FAILED) { |
| 175 | printf("Verify: Failed to verify signature.\n"); |
| 176 | return result; |
| 177 | } |
| 178 | if (result != KM_ERROR_OK) { |
| 179 | printf("Verify: FinishOperation failed: %d\n", result); |
| 180 | return result; |
| 181 | } |
| 182 | printf("Verify: OK\n"); |
| 183 | return 0; |
| 184 | } |
| 185 | |
| 186 | } // namespace |
| 187 | |
| 188 | int main(int argc, char** argv) { |
| 189 | CommandLine::Init(argc, argv); |
| 190 | CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 191 | CommandLine::StringVector args = command_line->GetArgs(); |
| 192 | if (args.empty()) { |
| 193 | PrintUsageAndExit(); |
| 194 | } |
| 195 | if (args[0] == "add-entropy") { |
| 196 | return AddEntropy(command_line->GetSwitchValueASCII("input")); |
| 197 | } else if (args[0] == "generate") { |
| 198 | return GenerateKey(command_line->GetSwitchValueASCII("name")); |
| 199 | } else if (args[0] == "get-chars") { |
| 200 | return GetCharacteristics(command_line->GetSwitchValueASCII("name")); |
| 201 | } else if (args[0] == "export") { |
| 202 | return ExportKey(command_line->GetSwitchValueASCII("name")); |
| 203 | } else if (args[0] == "delete") { |
| 204 | return DeleteKey(command_line->GetSwitchValueASCII("name")); |
| 205 | } else if (args[0] == "delete-all") { |
| 206 | return DeleteAllKeys(); |
| 207 | } else if (args[0] == "exists") { |
| 208 | return DoesKeyExist(command_line->GetSwitchValueASCII("name")); |
| 209 | } else if (args[0] == "list") { |
| 210 | return List(command_line->GetSwitchValueASCII("prefix")); |
| 211 | } else if (args[0] == "sign-verify") { |
| 212 | return SignAndVerify(command_line->GetSwitchValueASCII("name")); |
| 213 | } else { |
| 214 | PrintUsageAndExit(); |
| 215 | } |
| 216 | return 0; |
| 217 | } |