Home | History | Annotate | Download | only in keystore
      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