blob: 34f1d9c153e4aa58fb41aa982357e19d2d236ca9 [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>
Kenny Roota91203b2012-02-15 15:00:46 -080021
Kenny Root07438c82012-11-02 15:41:02 -070022#include <keystore/IKeystoreService.h>
23#include <binder/IPCThreadState.h>
24#include <binder/IServiceManager.h>
Kenny Roota91203b2012-02-15 15:00:46 -080025
Kenny Root07438c82012-11-02 15:41:02 -070026#include <keystore/keystore.h>
27
28using namespace android;
Kenny Roota91203b2012-02-15 15:00:46 -080029
30static const char* responses[] = {
31 NULL,
32 /* [NO_ERROR] = */ "No error",
33 /* [LOCKED] = */ "Locked",
34 /* [UNINITIALIZED] = */ "Uninitialized",
35 /* [SYSTEM_ERROR] = */ "System error",
36 /* [PROTOCOL_ERROR] = */ "Protocol error",
37 /* [PERMISSION_DENIED] = */ "Permission denied",
38 /* [KEY_NOT_FOUND] = */ "Key not found",
39 /* [VALUE_CORRUPTED] = */ "Value corrupted",
40 /* [UNDEFINED_ACTION] = */ "Undefined action",
41 /* [WRONG_PASSWORD] = */ "Wrong password (last chance)",
42 /* [WRONG_PASSWORD + 1] = */ "Wrong password (2 tries left)",
43 /* [WRONG_PASSWORD + 2] = */ "Wrong password (3 tries left)",
44 /* [WRONG_PASSWORD + 3] = */ "Wrong password (4 tries left)",
45};
46
Kenny Root07438c82012-11-02 15:41:02 -070047#define NO_ARG_INT_RETURN(cmd) \
48 do { \
49 if (strcmp(argv[1], #cmd) == 0) { \
50 int32_t ret = service->cmd(); \
51 if (ret < 0) { \
52 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
53 return 1; \
54 } else { \
55 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
56 return 0; \
57 } \
58 } \
59 } while (0)
60
61#define SINGLE_ARG_INT_RETURN(cmd) \
62 do { \
63 if (strcmp(argv[1], #cmd) == 0) { \
64 if (argc < 3) { \
65 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
66 return 1; \
67 } \
68 int32_t ret = service->cmd(String16(argv[2])); \
69 if (ret < 0) { \
70 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
71 return 1; \
72 } else { \
73 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
74 return 0; \
75 } \
76 } \
77 } while (0)
78
Chad Brubaker94436162015-05-12 15:18:26 -070079#define SINGLE_INT_ARG_INT_RETURN(cmd) \
80 do { \
81 if (strcmp(argv[1], #cmd) == 0) { \
82 if (argc < 3) { \
83 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
84 return 1; \
85 } \
86 int32_t ret = service->cmd(atoi(argv[2])); \
87 if (ret < 0) { \
88 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
89 return 1; \
90 } else { \
91 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
92 return 0; \
93 } \
94 } \
95 } while (0)
96
Kenny Rootb88c3eb2013-02-13 14:43:43 -080097#define SINGLE_ARG_PLUS_UID_INT_RETURN(cmd) \
98 do { \
99 if (strcmp(argv[1], #cmd) == 0) { \
100 if (argc < 3) { \
101 fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
102 return 1; \
103 } \
104 int uid = -1; \
105 if (argc > 3) { \
106 uid = atoi(argv[3]); \
Roman Mazure1a67a22015-09-17 12:55:53 +0300107 fprintf(stderr, "Working with uid %d\n", uid); \
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800108 } \
109 int32_t ret = service->cmd(String16(argv[2]), uid); \
110 if (ret < 0) { \
111 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
112 return 1; \
113 } else { \
114 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
115 return 0; \
116 } \
117 } \
118 } while (0)
119
Roman Mazure1a67a22015-09-17 12:55:53 +0300120#define STING_ARG_DATA_STDIN_PLUS_UID_PLUS_FLAGS_INT_RETURN(cmd) \
Kenny Root07438c82012-11-02 15:41:02 -0700121 do { \
122 if (strcmp(argv[1], #cmd) == 0) { \
123 if (argc < 3) { \
Roman Mazure1a67a22015-09-17 12:55:53 +0300124 fprintf(stderr, "Usage: %s " #cmd " <name> [<uid>, <flags>]\n", argv[0]); \
Kenny Root07438c82012-11-02 15:41:02 -0700125 return 1; \
126 } \
127 uint8_t* data; \
128 size_t dataSize; \
129 read_input(&data, &dataSize); \
Roman Mazure1a67a22015-09-17 12:55:53 +0300130 int uid = -1; \
131 if (argc > 3) { \
132 uid = atoi(argv[3]); \
133 fprintf(stderr, "Working with uid %d\n", uid); \
134 } \
135 int32_t flags = 0; \
136 if (argc > 4) { \
137 flags = int32_t(atoi(argv[4])); \
138 fprintf(stderr, "Using flags %04x\n", flags); \
139 } \
140 int32_t ret = service->cmd(String16(argv[2]), data, dataSize, uid, flags); \
141 free(data); \
Kenny Root07438c82012-11-02 15:41:02 -0700142 if (ret < 0) { \
143 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
144 return 1; \
145 } else { \
146 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
147 return 0; \
148 } \
149 } \
150 } while (0)
151
152#define SINGLE_ARG_DATA_RETURN(cmd) \
153 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 int32_t ret = service->cmd(String16(argv[2]), &data, &dataSize); \
162 if (ret < 0) { \
163 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
164 return 1; \
Roman Mazure1a67a22015-09-17 12:55:53 +0300165 } else if (ret) { \
Kenny Root07438c82012-11-02 15:41:02 -0700166 fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
167 return 1; \
Roman Mazure1a67a22015-09-17 12:55:53 +0300168 } else if (dataSize) { \
Kenny Root07438c82012-11-02 15:41:02 -0700169 fwrite(data, dataSize, 1, stdout); \
170 fflush(stdout); \
171 free(data); \
172 return 0; \
Roman Mazure1a67a22015-09-17 12:55:53 +0300173 } else { \
174 return 1; \
Kenny Root07438c82012-11-02 15:41:02 -0700175 } \
176 } \
177 } while (0)
178
Chad Brubaker94436162015-05-12 15:18:26 -0700179static int list(sp<IKeystoreService> service, const String16& name, int uid) {
Kenny Root07438c82012-11-02 15:41:02 -0700180 Vector<String16> matches;
Chad Brubaker94436162015-05-12 15:18:26 -0700181 int32_t ret = service->list(name, uid, &matches);
Kenny Root07438c82012-11-02 15:41:02 -0700182 if (ret < 0) {
Chad Brubaker94436162015-05-12 15:18:26 -0700183 fprintf(stderr, "list: could not connect: %d\n", ret);
Kenny Root07438c82012-11-02 15:41:02 -0700184 return 1;
185 } else if (ret != ::NO_ERROR) {
Chad Brubaker94436162015-05-12 15:18:26 -0700186 fprintf(stderr, "list: %s (%d)\n", responses[ret], ret);
Kenny Root07438c82012-11-02 15:41:02 -0700187 return 1;
188 } else {
189 Vector<String16>::const_iterator it = matches.begin();
190 for (; it != matches.end(); ++it) {
191 printf("%s\n", String8(*it).string());
192 }
193 return 0;
194 }
195}
196
Roman Mazure1a67a22015-09-17 12:55:53 +0300197#define BUF_SIZE 1024
198static void read_input(uint8_t** data, size_t* dataSize) {
199 char buffer[BUF_SIZE];
200 size_t contentSize = 0;
201 char *content = (char *) malloc(sizeof(char) * BUF_SIZE);
202
203 if (content == NULL) {
204 fprintf(stderr, "read_input: failed to allocate content");
205 exit(1);
206 }
207 content[0] = '\0';
208 while (fgets(buffer, BUF_SIZE, stdin)) {
209 char *old = content;
210 contentSize += strlen(buffer);
211 content = (char *) realloc(content, contentSize);
212 if (content == NULL) {
213 fprintf(stderr, "read_input: failed to reallocate content.");
214 free(old);
215 exit(1);
216 }
217 strcat(content, buffer);
218 }
219
220 if (ferror(stdin)) {
221 free(content);
222 fprintf(stderr, "read_input: error reading from stdin.");
223 exit(1);
224 }
225
226 *data = (uint8_t*) content;
227 *dataSize = contentSize;
228}
229
Kenny Roota91203b2012-02-15 15:00:46 -0800230int main(int argc, char* argv[])
231{
232 if (argc < 2) {
Kenny Root07438c82012-11-02 15:41:02 -0700233 fprintf(stderr, "Usage: %s action [parameter ...]\n", argv[0]);
Kenny Roota91203b2012-02-15 15:00:46 -0800234 return 1;
235 }
236
Kenny Root07438c82012-11-02 15:41:02 -0700237 sp<IServiceManager> sm = defaultServiceManager();
238 sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
239 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
Kenny Roota91203b2012-02-15 15:00:46 -0800240
Kenny Root07438c82012-11-02 15:41:02 -0700241 if (service == NULL) {
242 fprintf(stderr, "%s: error: could not connect to keystore service\n", argv[0]);
Kenny Roota91203b2012-02-15 15:00:46 -0800243 return 1;
244 }
Kenny Root07438c82012-11-02 15:41:02 -0700245
246 /*
247 * All the commands should return a value
248 */
249
Chad Brubaker94436162015-05-12 15:18:26 -0700250 SINGLE_INT_ARG_INT_RETURN(getState);
Kenny Root07438c82012-11-02 15:41:02 -0700251
252 SINGLE_ARG_DATA_RETURN(get);
253
Roman Mazure1a67a22015-09-17 12:55:53 +0300254 STING_ARG_DATA_STDIN_PLUS_UID_PLUS_FLAGS_INT_RETURN(insert);
Kenny Root07438c82012-11-02 15:41:02 -0700255
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800256 SINGLE_ARG_PLUS_UID_INT_RETURN(del);
Kenny Root07438c82012-11-02 15:41:02 -0700257
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800258 SINGLE_ARG_PLUS_UID_INT_RETURN(exist);
Kenny Root07438c82012-11-02 15:41:02 -0700259
Chad Brubaker94436162015-05-12 15:18:26 -0700260 if (strcmp(argv[1], "list") == 0) {
261 return list(service, argc < 3 ? String16("") : String16(argv[2]),
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800262 argc < 4 ? -1 : atoi(argv[3]));
Kenny Roota91203b2012-02-15 15:00:46 -0800263 }
Kenny Root07438c82012-11-02 15:41:02 -0700264
265 NO_ARG_INT_RETURN(reset);
266
Chad Brubakereecdd122015-05-07 10:19:40 -0700267 // TODO: notifyUserPasswordChanged
Kenny Root07438c82012-11-02 15:41:02 -0700268
Chad Brubaker94436162015-05-12 15:18:26 -0700269 SINGLE_INT_ARG_INT_RETURN(lock);
Kenny Root07438c82012-11-02 15:41:02 -0700270
Chad Brubakereecdd122015-05-07 10:19:40 -0700271 // TODO: unlock
Kenny Root07438c82012-11-02 15:41:02 -0700272
Chad Brubaker94436162015-05-12 15:18:26 -0700273 SINGLE_INT_ARG_INT_RETURN(isEmpty);
Kenny Root07438c82012-11-02 15:41:02 -0700274
Kenny Root0c540aa2013-04-03 09:22:15 -0700275 // TODO: generate
Kenny Root07438c82012-11-02 15:41:02 -0700276
277 SINGLE_ARG_DATA_RETURN(get_pubkey);
278
Roman Mazure1a67a22015-09-17 12:55:53 +0300279 SINGLE_ARG_PLUS_UID_INT_RETURN(grant);
Kenny Root07438c82012-11-02 15:41:02 -0700280
281 // TODO: ungrant
282
283 // TODO: getmtime
284
285 fprintf(stderr, "%s: unknown command: %s\n", argv[0], argv[1]);
286 return 1;
Kenny Roota91203b2012-02-15 15:00:46 -0800287}