blob: 428a9bc17fac40cb81075604ca8410a5cee04c56 [file] [log] [blame]
Kenny Roota91203b2012-02-15 15:00:46 -08001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdint.h>
19#include <string.h>
20#include <sys/types.h>
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -070021#include <vector>
Kenny Roota91203b2012-02-15 15:00:46 -080022
Rob Barnesbb6cabd2018-10-04 17:10:37 -060023#include <android/security/keystore/IKeystoreService.h>
Kenny Root07438c82012-11-02 15:41:02 -070024#include <binder/IPCThreadState.h>
25#include <binder/IServiceManager.h>
Kenny Roota91203b2012-02-15 15:00:46 -080026
Kenny Root07438c82012-11-02 15:41:02 -070027#include <keystore/keystore.h>
28
29using namespace android;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010030using namespace keystore;
Rob Barnesbb6cabd2018-10-04 17:10:37 -060031using android::security::keystore::IKeystoreService;
Kenny Roota91203b2012-02-15 15:00:46 -080032
33static const char* responses[] = {
Yi Konge353f252018-07-30 01:38:39 -070034 nullptr,
Kenny Roota91203b2012-02-15 15:00:46 -080035 /* [NO_ERROR] = */ "No error",
36 /* [LOCKED] = */ "Locked",
37 /* [UNINITIALIZED] = */ "Uninitialized",
38 /* [SYSTEM_ERROR] = */ "System error",
39 /* [PROTOCOL_ERROR] = */ "Protocol error",
40 /* [PERMISSION_DENIED] = */ "Permission denied",
41 /* [KEY_NOT_FOUND] = */ "Key not found",
42 /* [VALUE_CORRUPTED] = */ "Value corrupted",
43 /* [UNDEFINED_ACTION] = */ "Undefined action",
44 /* [WRONG_PASSWORD] = */ "Wrong password (last chance)",
45 /* [WRONG_PASSWORD + 1] = */ "Wrong password (2 tries left)",
46 /* [WRONG_PASSWORD + 2] = */ "Wrong password (3 tries left)",
47 /* [WRONG_PASSWORD + 3] = */ "Wrong password (4 tries left)",
48};
49
Kenny Root07438c82012-11-02 15:41:02 -070050#define SINGLE_ARG_INT_RETURN(cmd) \
51 do { \
52 if (strcmp(argv[1], #cmd) == 0) { \
53 if (argc < 3) { \
54 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
55 return 1; \
56 } \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -070057 int32_t ret = -1; \
58 service->cmd(String16(argv[2]), &ret); \
Kenny Root07438c82012-11-02 15:41:02 -070059 if (ret < 0) { \
60 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
61 return 1; \
62 } else { \
63 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
64 return 0; \
65 } \
66 } \
67 } while (0)
68
Chad Brubaker94436162015-05-12 15:18:26 -070069#define SINGLE_INT_ARG_INT_RETURN(cmd) \
70 do { \
71 if (strcmp(argv[1], #cmd) == 0) { \
72 if (argc < 3) { \
73 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
74 return 1; \
75 } \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -070076 int32_t ret = -1; \
77 service->cmd(atoi(argv[2]), &ret); \
Chad Brubaker94436162015-05-12 15:18:26 -070078 if (ret < 0) { \
79 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
80 return 1; \
81 } else { \
82 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
83 return 0; \
84 } \
85 } \
86 } while (0)
87
Kenny Rootb88c3eb2013-02-13 14:43:43 -080088#define SINGLE_ARG_PLUS_UID_INT_RETURN(cmd) \
89 do { \
90 if (strcmp(argv[1], #cmd) == 0) { \
91 if (argc < 3) { \
92 fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
93 return 1; \
94 } \
95 int uid = -1; \
96 if (argc > 3) { \
97 uid = atoi(argv[3]); \
98 fprintf(stderr, "Running as uid %d\n", uid); \
99 } \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700100 int32_t ret = -1; \
101 service->cmd(String16(argv[2]), uid, &ret); \
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800102 if (ret < 0) { \
103 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
104 return 1; \
105 } else { \
106 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
107 return 0; \
108 } \
109 } \
110 } while (0)
111
Chad Brubakerad6a7f52015-09-09 14:55:22 -0700112#define SINGLE_ARG_PLUS_UID_DATA_RETURN(cmd) \
113 do { \
114 if (strcmp(argv[1], #cmd) == 0) { \
115 if (argc < 3) { \
116 fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
117 return 1; \
118 } \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700119 std::vector<uint8_t> data; \
Chad Brubakerad6a7f52015-09-09 14:55:22 -0700120 int uid = -1; \
121 if (argc > 3) { \
122 uid = atoi(argv[3]); \
123 fprintf(stderr, "Running as uid %d\n", uid); \
124 } \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700125 ::android::binder::Status ret = service->cmd(String16(argv[2]), uid, &data); \
126 if (!ret.isOk()) { \
127 fprintf(stderr, "Exception code: %d\n", ret.exceptionCode()); \
Chad Brubakerad6a7f52015-09-09 14:55:22 -0700128 return 1; \
129 } else { \
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100130 fwrite(&data[0], data.size(), 1, stdout); \
Chad Brubakerad6a7f52015-09-09 14:55:22 -0700131 fflush(stdout); \
Chad Brubakerad6a7f52015-09-09 14:55:22 -0700132 return 0; \
133 } \
134 } \
135 } while (0)
136
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700137#define STRING_ARG_DATA_STDIN_INT_RETURN(cmd) \
Kenny Root07438c82012-11-02 15:41:02 -0700138 do { \
139 if (strcmp(argv[1], #cmd) == 0) { \
140 if (argc < 3) { \
141 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
142 return 1; \
143 } \
144 uint8_t* data; \
145 size_t dataSize; \
146 read_input(&data, &dataSize); \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700147 int32_t ret = -1; \
148 service->cmd(String16(argv[2]), data, dataSize, &ret); \
Kenny Root07438c82012-11-02 15:41:02 -0700149 if (ret < 0) { \
150 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
151 return 1; \
152 } else { \
153 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
154 return 0; \
155 } \
156 } \
157 } while (0)
158
159#define SINGLE_ARG_DATA_RETURN(cmd) \
160 do { \
161 if (strcmp(argv[1], #cmd) == 0) { \
162 if (argc < 3) { \
163 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
164 return 1; \
165 } \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700166 std::vector<uint8_t> data; \
167 ::android::binder::Status ret = service->cmd(String16(argv[2]), &data); \
168 if (!ret.isOk()) { \
169 fprintf(stderr, "Exception code: %d\n", ret.exceptionCode()); \
Kenny Root07438c82012-11-02 15:41:02 -0700170 return 1; \
171 } else { \
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100172 fwrite(&data[0], data.size(), 1, stdout); \
Kenny Root07438c82012-11-02 15:41:02 -0700173 fflush(stdout); \
Kenny Root07438c82012-11-02 15:41:02 -0700174 return 0; \
175 } \
176 } \
177 } while (0)
178
Chih-Hung Hsieh24b2a392016-07-28 10:35:24 -0700179static int list(const sp<IKeystoreService>& service, const String16& name, int uid) {
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700180 std::vector<String16> matches;
181 ::android::binder::Status ret = service->list(name, uid, &matches);
182
183 if (!ret.isOk()) {
184 fprintf(stderr, "list: exception (%d)\n", ret.exceptionCode());
Kenny Root07438c82012-11-02 15:41:02 -0700185 return 1;
186 } else {
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700187 std::vector<String16>::const_iterator it = matches.begin();
Kenny Root07438c82012-11-02 15:41:02 -0700188 for (; it != matches.end(); ++it) {
189 printf("%s\n", String8(*it).string());
190 }
191 return 0;
192 }
193}
194
Kenny Roota91203b2012-02-15 15:00:46 -0800195int main(int argc, char* argv[])
196{
197 if (argc < 2) {
Kenny Root07438c82012-11-02 15:41:02 -0700198 fprintf(stderr, "Usage: %s action [parameter ...]\n", argv[0]);
Kenny Roota91203b2012-02-15 15:00:46 -0800199 return 1;
200 }
201
Kenny Root07438c82012-11-02 15:41:02 -0700202 sp<IServiceManager> sm = defaultServiceManager();
203 sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
204 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
Kenny Roota91203b2012-02-15 15:00:46 -0800205
Yi Konge353f252018-07-30 01:38:39 -0700206 if (service == nullptr) {
Kenny Root07438c82012-11-02 15:41:02 -0700207 fprintf(stderr, "%s: error: could not connect to keystore service\n", argv[0]);
Kenny Roota91203b2012-02-15 15:00:46 -0800208 return 1;
209 }
Kenny Root07438c82012-11-02 15:41:02 -0700210
211 /*
212 * All the commands should return a value
213 */
214
Chad Brubaker94436162015-05-12 15:18:26 -0700215 SINGLE_INT_ARG_INT_RETURN(getState);
Kenny Root07438c82012-11-02 15:41:02 -0700216
Chad Brubakerad6a7f52015-09-09 14:55:22 -0700217 SINGLE_ARG_PLUS_UID_DATA_RETURN(get);
Kenny Root07438c82012-11-02 15:41:02 -0700218
219 // TODO: insert
220
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800221 SINGLE_ARG_PLUS_UID_INT_RETURN(del);
Kenny Root07438c82012-11-02 15:41:02 -0700222
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800223 SINGLE_ARG_PLUS_UID_INT_RETURN(exist);
Kenny Root07438c82012-11-02 15:41:02 -0700224
Chad Brubaker94436162015-05-12 15:18:26 -0700225 if (strcmp(argv[1], "list") == 0) {
226 return list(service, argc < 3 ? String16("") : String16(argv[2]),
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800227 argc < 4 ? -1 : atoi(argv[3]));
Kenny Roota91203b2012-02-15 15:00:46 -0800228 }
Kenny Root07438c82012-11-02 15:41:02 -0700229
Chad Brubakereecdd122015-05-07 10:19:40 -0700230 // TODO: notifyUserPasswordChanged
Kenny Root07438c82012-11-02 15:41:02 -0700231
Chad Brubaker94436162015-05-12 15:18:26 -0700232 SINGLE_INT_ARG_INT_RETURN(lock);
Kenny Root07438c82012-11-02 15:41:02 -0700233
Chad Brubakereecdd122015-05-07 10:19:40 -0700234 // TODO: unlock
Kenny Root07438c82012-11-02 15:41:02 -0700235
Chad Brubaker94436162015-05-12 15:18:26 -0700236 SINGLE_INT_ARG_INT_RETURN(isEmpty);
Kenny Root07438c82012-11-02 15:41:02 -0700237
Kenny Root0c540aa2013-04-03 09:22:15 -0700238 // TODO: generate
Kenny Root07438c82012-11-02 15:41:02 -0700239
Kenny Root07438c82012-11-02 15:41:02 -0700240 // TODO: grant
241
242 // TODO: ungrant
243
244 // TODO: getmtime
245
246 fprintf(stderr, "%s: unknown command: %s\n", argv[0], argv[1]);
247 return 1;
Kenny Roota91203b2012-02-15 15:00:46 -0800248}