blob: 2705a194aead6ae86561383b129e4ac611502ea3 [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 NO_ARG_INT_RETURN(cmd) \
51 do { \
52 if (strcmp(argv[1], #cmd) == 0) { \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -070053 int32_t ret = -1; \
54 service->cmd(&ret); \
Kenny Root07438c82012-11-02 15:41:02 -070055 if (ret < 0) { \
56 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
57 return 1; \
58 } else { \
59 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
60 return 0; \
61 } \
62 } \
63 } while (0)
64
65#define SINGLE_ARG_INT_RETURN(cmd) \
66 do { \
67 if (strcmp(argv[1], #cmd) == 0) { \
68 if (argc < 3) { \
69 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
70 return 1; \
71 } \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -070072 int32_t ret = -1; \
73 service->cmd(String16(argv[2]), &ret); \
Kenny Root07438c82012-11-02 15:41:02 -070074 if (ret < 0) { \
75 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
76 return 1; \
77 } else { \
78 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
79 return 0; \
80 } \
81 } \
82 } while (0)
83
Chad Brubaker94436162015-05-12 15:18:26 -070084#define SINGLE_INT_ARG_INT_RETURN(cmd) \
85 do { \
86 if (strcmp(argv[1], #cmd) == 0) { \
87 if (argc < 3) { \
88 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
89 return 1; \
90 } \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -070091 int32_t ret = -1; \
92 service->cmd(atoi(argv[2]), &ret); \
Chad Brubaker94436162015-05-12 15:18:26 -070093 if (ret < 0) { \
94 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
95 return 1; \
96 } else { \
97 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
98 return 0; \
99 } \
100 } \
101 } while (0)
102
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800103#define SINGLE_ARG_PLUS_UID_INT_RETURN(cmd) \
104 do { \
105 if (strcmp(argv[1], #cmd) == 0) { \
106 if (argc < 3) { \
107 fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
108 return 1; \
109 } \
110 int uid = -1; \
111 if (argc > 3) { \
112 uid = atoi(argv[3]); \
113 fprintf(stderr, "Running as uid %d\n", uid); \
114 } \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700115 int32_t ret = -1; \
116 service->cmd(String16(argv[2]), uid, &ret); \
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800117 if (ret < 0) { \
118 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
119 return 1; \
120 } else { \
121 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
122 return 0; \
123 } \
124 } \
125 } while (0)
126
Chad Brubakerad6a7f52015-09-09 14:55:22 -0700127#define SINGLE_ARG_PLUS_UID_DATA_RETURN(cmd) \
128 do { \
129 if (strcmp(argv[1], #cmd) == 0) { \
130 if (argc < 3) { \
131 fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
132 return 1; \
133 } \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700134 std::vector<uint8_t> data; \
Chad Brubakerad6a7f52015-09-09 14:55:22 -0700135 int uid = -1; \
136 if (argc > 3) { \
137 uid = atoi(argv[3]); \
138 fprintf(stderr, "Running as uid %d\n", uid); \
139 } \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700140 ::android::binder::Status ret = service->cmd(String16(argv[2]), uid, &data); \
141 if (!ret.isOk()) { \
142 fprintf(stderr, "Exception code: %d\n", ret.exceptionCode()); \
Chad Brubakerad6a7f52015-09-09 14:55:22 -0700143 return 1; \
144 } else { \
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100145 fwrite(&data[0], data.size(), 1, stdout); \
Chad Brubakerad6a7f52015-09-09 14:55:22 -0700146 fflush(stdout); \
Chad Brubakerad6a7f52015-09-09 14:55:22 -0700147 return 0; \
148 } \
149 } \
150 } while (0)
151
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700152#define STRING_ARG_DATA_STDIN_INT_RETURN(cmd) \
Kenny Root07438c82012-11-02 15:41:02 -0700153 do { \
154 if (strcmp(argv[1], #cmd) == 0) { \
155 if (argc < 3) { \
156 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
157 return 1; \
158 } \
159 uint8_t* data; \
160 size_t dataSize; \
161 read_input(&data, &dataSize); \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700162 int32_t ret = -1; \
163 service->cmd(String16(argv[2]), data, dataSize, &ret); \
Kenny Root07438c82012-11-02 15:41:02 -0700164 if (ret < 0) { \
165 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
166 return 1; \
167 } else { \
168 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
169 return 0; \
170 } \
171 } \
172 } while (0)
173
174#define SINGLE_ARG_DATA_RETURN(cmd) \
175 do { \
176 if (strcmp(argv[1], #cmd) == 0) { \
177 if (argc < 3) { \
178 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
179 return 1; \
180 } \
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700181 std::vector<uint8_t> data; \
182 ::android::binder::Status ret = service->cmd(String16(argv[2]), &data); \
183 if (!ret.isOk()) { \
184 fprintf(stderr, "Exception code: %d\n", ret.exceptionCode()); \
Kenny Root07438c82012-11-02 15:41:02 -0700185 return 1; \
186 } else { \
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100187 fwrite(&data[0], data.size(), 1, stdout); \
Kenny Root07438c82012-11-02 15:41:02 -0700188 fflush(stdout); \
Kenny Root07438c82012-11-02 15:41:02 -0700189 return 0; \
190 } \
191 } \
192 } while (0)
193
Chih-Hung Hsieh24b2a392016-07-28 10:35:24 -0700194static int list(const sp<IKeystoreService>& service, const String16& name, int uid) {
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700195 std::vector<String16> matches;
196 ::android::binder::Status ret = service->list(name, uid, &matches);
197
198 if (!ret.isOk()) {
199 fprintf(stderr, "list: exception (%d)\n", ret.exceptionCode());
Kenny Root07438c82012-11-02 15:41:02 -0700200 return 1;
201 } else {
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700202 std::vector<String16>::const_iterator it = matches.begin();
Kenny Root07438c82012-11-02 15:41:02 -0700203 for (; it != matches.end(); ++it) {
204 printf("%s\n", String8(*it).string());
205 }
206 return 0;
207 }
208}
209
Kenny Roota91203b2012-02-15 15:00:46 -0800210int main(int argc, char* argv[])
211{
212 if (argc < 2) {
Kenny Root07438c82012-11-02 15:41:02 -0700213 fprintf(stderr, "Usage: %s action [parameter ...]\n", argv[0]);
Kenny Roota91203b2012-02-15 15:00:46 -0800214 return 1;
215 }
216
Kenny Root07438c82012-11-02 15:41:02 -0700217 sp<IServiceManager> sm = defaultServiceManager();
218 sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
219 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
Kenny Roota91203b2012-02-15 15:00:46 -0800220
Yi Konge353f252018-07-30 01:38:39 -0700221 if (service == nullptr) {
Kenny Root07438c82012-11-02 15:41:02 -0700222 fprintf(stderr, "%s: error: could not connect to keystore service\n", argv[0]);
Kenny Roota91203b2012-02-15 15:00:46 -0800223 return 1;
224 }
Kenny Root07438c82012-11-02 15:41:02 -0700225
226 /*
227 * All the commands should return a value
228 */
229
Chad Brubaker94436162015-05-12 15:18:26 -0700230 SINGLE_INT_ARG_INT_RETURN(getState);
Kenny Root07438c82012-11-02 15:41:02 -0700231
Chad Brubakerad6a7f52015-09-09 14:55:22 -0700232 SINGLE_ARG_PLUS_UID_DATA_RETURN(get);
Kenny Root07438c82012-11-02 15:41:02 -0700233
234 // TODO: insert
235
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800236 SINGLE_ARG_PLUS_UID_INT_RETURN(del);
Kenny Root07438c82012-11-02 15:41:02 -0700237
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800238 SINGLE_ARG_PLUS_UID_INT_RETURN(exist);
Kenny Root07438c82012-11-02 15:41:02 -0700239
Chad Brubaker94436162015-05-12 15:18:26 -0700240 if (strcmp(argv[1], "list") == 0) {
241 return list(service, argc < 3 ? String16("") : String16(argv[2]),
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800242 argc < 4 ? -1 : atoi(argv[3]));
Kenny Roota91203b2012-02-15 15:00:46 -0800243 }
Kenny Root07438c82012-11-02 15:41:02 -0700244
245 NO_ARG_INT_RETURN(reset);
246
Chad Brubakereecdd122015-05-07 10:19:40 -0700247 // TODO: notifyUserPasswordChanged
Kenny Root07438c82012-11-02 15:41:02 -0700248
Chad Brubaker94436162015-05-12 15:18:26 -0700249 SINGLE_INT_ARG_INT_RETURN(lock);
Kenny Root07438c82012-11-02 15:41:02 -0700250
Chad Brubakereecdd122015-05-07 10:19:40 -0700251 // TODO: unlock
Kenny Root07438c82012-11-02 15:41:02 -0700252
Chad Brubaker94436162015-05-12 15:18:26 -0700253 SINGLE_INT_ARG_INT_RETURN(isEmpty);
Kenny Root07438c82012-11-02 15:41:02 -0700254
Kenny Root0c540aa2013-04-03 09:22:15 -0700255 // TODO: generate
Kenny Root07438c82012-11-02 15:41:02 -0700256
Kenny Root07438c82012-11-02 15:41:02 -0700257 // TODO: grant
258
259 // TODO: ungrant
260
261 // TODO: getmtime
262
263 fprintf(stderr, "%s: unknown command: %s\n", argv[0], argv[1]);
264 return 1;
Kenny Roota91203b2012-02-15 15:00:46 -0800265}