1 /* 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> 21 22 #include <keystore/IKeystoreService.h> 23 #include <binder/IPCThreadState.h> 24 #include <binder/IServiceManager.h> 25 26 #include <keystore/keystore.h> 27 28 using namespace android; 29 30 static 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 47 #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 79 #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 102 #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 148 static int saw(sp<IKeystoreService> service, const String16& name, int uid) { 149 Vector<String16> matches; 150 int32_t ret = service->saw(name, uid, &matches); 151 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 166 int main(int argc, char* argv[]) 167 { 168 if (argc < 2) { 169 fprintf(stderr, "Usage: %s action [parameter ...]\n", argv[0]); 170 return 1; 171 } 172 173 sp<IServiceManager> sm = defaultServiceManager(); 174 sp<IBinder> binder = sm->getService(String16("android.security.keystore")); 175 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder); 176 177 if (service == NULL) { 178 fprintf(stderr, "%s: error: could not connect to keystore service\n", argv[0]); 179 return 1; 180 } 181 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 192 SINGLE_ARG_PLUS_UID_INT_RETURN(del); 193 194 SINGLE_ARG_PLUS_UID_INT_RETURN(exist); 195 196 if (strcmp(argv[1], "saw") == 0) { 197 return saw(service, argc < 3 ? String16("") : String16(argv[2]), 198 argc < 4 ? -1 : atoi(argv[3])); 199 } 200 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 211 // TODO: generate 212 213 SINGLE_ARG_DATA_RETURN(get_pubkey); 214 215 SINGLE_ARG_PLUS_UID_INT_RETURN(del_key); 216 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; 225 } 226