blob: 1e1989092d95881ed777d73d6aa88dbe6ff8f0db [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
Kenny Rootb88c3eb2013-02-13 14:43:43 -080079#define SINGLE_ARG_PLUS_UID_INT_RETURN(cmd) \
80 do { \
81 if (strcmp(argv[1], #cmd) == 0) { \
82 if (argc < 3) { \
83 fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
84 return 1; \
85 } \
86 int uid = -1; \
87 if (argc > 3) { \
88 uid = atoi(argv[3]); \
89 fprintf(stderr, "Running as uid %d\n", uid); \
90 } \
91 int32_t ret = service->cmd(String16(argv[2]), uid); \
92 if (ret < 0) { \
93 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
94 return 1; \
95 } else { \
96 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
97 return 0; \
98 } \
99 } \
100 } while (0)
101
Kenny Root07438c82012-11-02 15:41:02 -0700102#define STING_ARG_DATA_STDIN_INT_RETURN(cmd) \
103 do { \
104 if (strcmp(argv[1], #cmd) == 0) { \
105 if (argc < 3) { \
106 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
107 return 1; \
108 } \
109 uint8_t* data; \
110 size_t dataSize; \
111 read_input(&data, &dataSize); \
112 int32_t ret = service->cmd(String16(argv[2]), data, dataSize); \
113 if (ret < 0) { \
114 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
115 return 1; \
116 } else { \
117 printf(#cmd ": %s (%d)\n", responses[ret], ret); \
118 return 0; \
119 } \
120 } \
121 } while (0)
122
123#define SINGLE_ARG_DATA_RETURN(cmd) \
124 do { \
125 if (strcmp(argv[1], #cmd) == 0) { \
126 if (argc < 3) { \
127 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
128 return 1; \
129 } \
130 uint8_t* data; \
131 size_t dataSize; \
132 int32_t ret = service->cmd(String16(argv[2]), &data, &dataSize); \
133 if (ret < 0) { \
134 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
135 return 1; \
136 } else if (ret != ::NO_ERROR) { \
137 fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
138 return 1; \
139 } else { \
140 fwrite(data, dataSize, 1, stdout); \
141 fflush(stdout); \
142 free(data); \
143 return 0; \
144 } \
145 } \
146 } while (0)
147
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800148static int saw(sp<IKeystoreService> service, const String16& name, int uid) {
Kenny Root07438c82012-11-02 15:41:02 -0700149 Vector<String16> matches;
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800150 int32_t ret = service->saw(name, uid, &matches);
Kenny Root07438c82012-11-02 15:41:02 -0700151 if (ret < 0) {
152 fprintf(stderr, "saw: could not connect: %d\n", ret);
153 return 1;
154 } else if (ret != ::NO_ERROR) {
155 fprintf(stderr, "saw: %s (%d)\n", responses[ret], ret);
156 return 1;
157 } else {
158 Vector<String16>::const_iterator it = matches.begin();
159 for (; it != matches.end(); ++it) {
160 printf("%s\n", String8(*it).string());
161 }
162 return 0;
163 }
164}
165
Kenny Roota91203b2012-02-15 15:00:46 -0800166int main(int argc, char* argv[])
167{
168 if (argc < 2) {
Kenny Root07438c82012-11-02 15:41:02 -0700169 fprintf(stderr, "Usage: %s action [parameter ...]\n", argv[0]);
Kenny Roota91203b2012-02-15 15:00:46 -0800170 return 1;
171 }
172
Kenny Root07438c82012-11-02 15:41:02 -0700173 sp<IServiceManager> sm = defaultServiceManager();
174 sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
175 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
Kenny Roota91203b2012-02-15 15:00:46 -0800176
Kenny Root07438c82012-11-02 15:41:02 -0700177 if (service == NULL) {
178 fprintf(stderr, "%s: error: could not connect to keystore service\n", argv[0]);
Kenny Roota91203b2012-02-15 15:00:46 -0800179 return 1;
180 }
Kenny Root07438c82012-11-02 15:41:02 -0700181
182 /*
183 * All the commands should return a value
184 */
185
186 NO_ARG_INT_RETURN(test);
187
188 SINGLE_ARG_DATA_RETURN(get);
189
190 // TODO: insert
191
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800192 SINGLE_ARG_PLUS_UID_INT_RETURN(del);
Kenny Root07438c82012-11-02 15:41:02 -0700193
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800194 SINGLE_ARG_PLUS_UID_INT_RETURN(exist);
Kenny Root07438c82012-11-02 15:41:02 -0700195
196 if (strcmp(argv[1], "saw") == 0) {
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800197 return saw(service, argc < 3 ? String16("") : String16(argv[2]),
198 argc < 4 ? -1 : atoi(argv[3]));
Kenny Roota91203b2012-02-15 15:00:46 -0800199 }
Kenny Root07438c82012-11-02 15:41:02 -0700200
201 NO_ARG_INT_RETURN(reset);
202
203 SINGLE_ARG_INT_RETURN(password);
204
205 NO_ARG_INT_RETURN(lock);
206
207 SINGLE_ARG_INT_RETURN(unlock);
208
209 NO_ARG_INT_RETURN(zero);
210
Kenny Root0c540aa2013-04-03 09:22:15 -0700211 // TODO: generate
Kenny Root07438c82012-11-02 15:41:02 -0700212
213 SINGLE_ARG_DATA_RETURN(get_pubkey);
214
Kenny Rootb88c3eb2013-02-13 14:43:43 -0800215 SINGLE_ARG_PLUS_UID_INT_RETURN(del_key);
Kenny Root07438c82012-11-02 15:41:02 -0700216
217 // TODO: grant
218
219 // TODO: ungrant
220
221 // TODO: getmtime
222
223 fprintf(stderr, "%s: unknown command: %s\n", argv[0], argv[1]);
224 return 1;
Kenny Roota91203b2012-02-15 15:00:46 -0800225}