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//#define LOG_NDEBUG 0
18#define LOG_TAG "keystore"
19
20#include <binder/IPCThreadState.h>
21#include <binder/IServiceManager.h>
22
23#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
24#include <android/system/wifi/keystore/1.0/IKeystore.h>
25#include <wifikeystorehal/keystore.h>
26
27#include <cutils/log.h>
28
29#include "entropy.h"
30#include "key_store_service.h"
31#include "keystore.h"
32#include "permissions.h"
33#include "legacy_keymaster_device_wrapper.h"
34#include "include/keystore/keystore_hidl_support.h"
35#include "include/keystore/keystore_return_types.h"
36
37/* KeyStore is a secured storage for key-value pairs. In this implementation,
38 * each file stores one key-value pair. Keys are encoded in file names, and
39 * values are encrypted with checksums. The encryption key is protected by a
40 * user-defined password. To keep things simple, buffers are always larger than
41 * the maximum space we needed, so boundary checks on buffers are omitted. */
42
43using ::android::system::wifi::keystore::V1_0::IKeystore;
44using ::android::system::wifi::keystore::V1_0::implementation::Keystore;
45using ::android::hardware::configureRpcThreadpool;
46
47/**
48 * TODO implement keystore daemon using binderized keymaster HAL.
49 */
50
51int main(int argc, char* argv[]) {
52    using android::hardware::hidl_string;
53    if (argc < 2) {
54        ALOGE("A directory must be specified!");
55        return 1;
56    }
57    if (chdir(argv[1]) == -1) {
58        ALOGE("chdir: %s: %s", argv[1], strerror(errno));
59        return 1;
60    }
61
62    Entropy entropy;
63    if (!entropy.open()) {
64        return 1;
65    }
66
67    auto dev = android::hardware::keymaster::V3_0::IKeymasterDevice::getService();
68    if (dev.get() == nullptr) {
69        return -1;
70    }
71    auto fallback = android::keystore::makeSoftwareKeymasterDevice();
72    if (dev.get() == nullptr) {
73        return -1;
74    }
75
76    if (configure_selinux() == -1) {
77        return -1;
78    }
79
80    bool allowNewFallbackDevice = false;
81
82    keystore::KeyStoreServiceReturnCode rc;
83    rc = KS_HANDLE_HIDL_ERROR(dev->getHardwareFeatures(
84            [&] (bool, bool, bool, bool supportsAttestation, bool, const hidl_string&,
85                 const hidl_string&) {
86                // Attestation support indicates the hardware is keymaster 2.0 or higher.
87                // For these devices we will not allow the fallback device for import or generation
88                // of keys. The fallback device is only used for legacy keys present on the device.
89                allowNewFallbackDevice = !supportsAttestation;
90            }));
91
92    if (!rc.isOk()) {
93        return -1;
94    }
95
96    KeyStore keyStore(&entropy, dev, fallback, allowNewFallbackDevice);
97    keyStore.initialize();
98    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
99    android::sp<keystore::KeyStoreService> service = new keystore::KeyStoreService(&keyStore);
100    android::status_t ret = sm->addService(android::String16("android.security.keystore"), service);
101    if (ret != android::OK) {
102        ALOGE("Couldn't register binder service!");
103        return -1;
104    }
105
106    /**
107     * Register the wifi keystore HAL service to run in passthrough mode.
108     * This will spawn off a new thread which will service the HIDL
109     * transactions.
110     */
111    configureRpcThreadpool(1, false /* callerWillJoin */);
112    android::sp<IKeystore> wifiKeystoreHalService = new Keystore();
113    android::status_t err = wifiKeystoreHalService->registerAsService();
114    if (ret != android::OK) {
115        ALOGE("Cannot register wifi keystore HAL service: %d", err);
116    }
117
118    /*
119     * This thread is just going to process Binder transactions.
120     */
121    android::IPCThreadState::self()->joinThreadPool();
122    return 1;
123}
124