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