/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <vector>

#include <android/security/keystore/IKeystoreService.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>

#include <keystore/keystore.h>

using namespace android;
using namespace keystore;
using android::security::keystore::IKeystoreService;

static const char* responses[] = {
    nullptr,
    /* [NO_ERROR]           = */ "No error",
    /* [LOCKED]             = */ "Locked",
    /* [UNINITIALIZED]      = */ "Uninitialized",
    /* [SYSTEM_ERROR]       = */ "System error",
    /* [PROTOCOL_ERROR]     = */ "Protocol error",
    /* [PERMISSION_DENIED]  = */ "Permission denied",
    /* [KEY_NOT_FOUND]      = */ "Key not found",
    /* [VALUE_CORRUPTED]    = */ "Value corrupted",
    /* [UNDEFINED_ACTION]   = */ "Undefined action",
    /* [WRONG_PASSWORD]     = */ "Wrong password (last chance)",
    /* [WRONG_PASSWORD + 1] = */ "Wrong password (2 tries left)",
    /* [WRONG_PASSWORD + 2] = */ "Wrong password (3 tries left)",
    /* [WRONG_PASSWORD + 3] = */ "Wrong password (4 tries left)",
};

#define SINGLE_ARG_INT_RETURN(cmd) \
    do { \
        if (strcmp(argv[1], #cmd) == 0) { \
            if (argc < 3) { \
                fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
                return 1; \
            } \
            int32_t ret = -1; \
            service->cmd(String16(argv[2]), &ret); \
            if (ret < 0) { \
                fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                return 1; \
            } else { \
                printf(#cmd ": %s (%d)\n", responses[ret], ret); \
                return 0; \
            } \
        } \
    } while (0)

#define SINGLE_INT_ARG_INT_RETURN(cmd) \
    do { \
        if (strcmp(argv[1], #cmd) == 0) { \
            if (argc < 3) { \
                fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
                return 1; \
            } \
            int32_t ret = -1; \
            service->cmd(atoi(argv[2]), &ret); \
            if (ret < 0) { \
                fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                return 1; \
            } else { \
                printf(#cmd ": %s (%d)\n", responses[ret], ret); \
                return 0; \
            } \
        } \
    } while (0)

#define SINGLE_ARG_PLUS_UID_INT_RETURN(cmd) \
    do { \
        if (strcmp(argv[1], #cmd) == 0) { \
            if (argc < 3) { \
                fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
                return 1; \
            } \
            int uid = -1; \
            if (argc > 3) { \
                uid = atoi(argv[3]); \
                fprintf(stderr, "Running as uid %d\n", uid); \
            } \
            int32_t ret = -1; \
            service->cmd(String16(argv[2]), uid, &ret); \
            if (ret < 0) { \
                fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                return 1; \
            } else { \
                printf(#cmd ": %s (%d)\n", responses[ret], ret); \
                return 0; \
            } \
        } \
    } while (0)

#define SINGLE_ARG_PLUS_UID_DATA_RETURN(cmd) \
    do { \
        if (strcmp(argv[1], #cmd) == 0) { \
            if (argc < 3) { \
                fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
                return 1; \
            } \
            std::vector<uint8_t> data; \
            int uid = -1; \
            if (argc > 3) { \
                uid = atoi(argv[3]); \
                fprintf(stderr, "Running as uid %d\n", uid); \
            } \
            ::android::binder::Status ret = service->cmd(String16(argv[2]), uid, &data); \
            if (!ret.isOk()) { \
                fprintf(stderr, "Exception code: %d\n", ret.exceptionCode()); \
                return 1; \
            } else { \
                fwrite(&data[0], data.size(), 1, stdout); \
                fflush(stdout); \
                return 0; \
            } \
        } \
    } while (0)

#define STRING_ARG_DATA_STDIN_INT_RETURN(cmd) \
    do { \
        if (strcmp(argv[1], #cmd) == 0) { \
            if (argc < 3) { \
                fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
                return 1; \
            } \
            uint8_t* data; \
            size_t dataSize; \
            read_input(&data, &dataSize); \
            int32_t ret = -1; \
            service->cmd(String16(argv[2]), data, dataSize, &ret); \
            if (ret < 0) { \
                fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                return 1; \
            } else { \
                printf(#cmd ": %s (%d)\n", responses[ret], ret); \
                return 0; \
            } \
        } \
    } while (0)

#define SINGLE_ARG_DATA_RETURN(cmd) \
    do { \
        if (strcmp(argv[1], #cmd) == 0) { \
            if (argc < 3) { \
                fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
                return 1; \
            } \
            std::vector<uint8_t> data; \
            ::android::binder::Status ret = service->cmd(String16(argv[2]), &data); \
            if (!ret.isOk()) { \
                fprintf(stderr, "Exception code: %d\n", ret.exceptionCode()); \
                return 1; \
            } else { \
                fwrite(&data[0], data.size(), 1, stdout); \
                fflush(stdout); \
                return 0; \
            } \
        } \
    } while (0)

static int list(const sp<IKeystoreService>& service, const String16& name, int uid) {
    std::vector<String16> matches;
    ::android::binder::Status ret = service->list(name, uid, &matches);

    if (!ret.isOk()) {
        fprintf(stderr, "list: exception (%d)\n", ret.exceptionCode());
        return 1;
    } else {
        std::vector<String16>::const_iterator it = matches.begin();
        for (; it != matches.end(); ++it) {
            printf("%s\n", String8(*it).string());
        }
        return 0;
    }
}

int main(int argc, char* argv[])
{
    if (argc < 2) {
        fprintf(stderr, "Usage: %s action [parameter ...]\n", argv[0]);
        return 1;
    }

    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);

    if (service == nullptr) {
        fprintf(stderr, "%s: error: could not connect to keystore service\n", argv[0]);
        return 1;
    }

    /*
     * All the commands should return a value
     */

    SINGLE_INT_ARG_INT_RETURN(getState);

    SINGLE_ARG_PLUS_UID_DATA_RETURN(get);

    // TODO: insert

    SINGLE_ARG_PLUS_UID_INT_RETURN(del);

    SINGLE_ARG_PLUS_UID_INT_RETURN(exist);

    if (strcmp(argv[1], "list") == 0) {
        return list(service, argc < 3 ? String16("") : String16(argv[2]),
                argc < 4 ? -1 : atoi(argv[3]));
    }

    // TODO: notifyUserPasswordChanged

    SINGLE_INT_ARG_INT_RETURN(lock);

    // TODO: unlock

    SINGLE_INT_ARG_INT_RETURN(isEmpty);

    // TODO: generate

    // TODO: grant

    // TODO: ungrant

    // TODO: getmtime

    fprintf(stderr, "%s: unknown command: %s\n", argv[0], argv[1]);
    return 1;
}
