summaryrefslogtreecommitdiff
path: root/keystore/keystore_main.cpp
blob: 52e83c85c8c2286e3d959ae4f2efa85ac6431737 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
 * 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.
 */

#define LOG_TAG "keystore"

#include <android-base/logging.h>
#include <android/hidl/manager/1.1/IServiceManager.h>
#include <android/security/IKeystoreService.h>
#include <android/system/wifi/keystore/1.0/IKeystore.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <hidl/HidlTransportSupport.h>
#include <keymasterV4_0/Keymaster3.h>
#include <keymasterV4_0/Keymaster4.h>
#include <utils/StrongPointer.h>
#include <wifikeystorehal/keystore.h>

#include <keystore/keystore_hidl_support.h>
#include <keystore/keystore_return_types.h>

#include "KeyStore.h"
#include "key_store_service.h"
#include "legacy_keymaster_device_wrapper.h"
#include "permissions.h"

/* KeyStore is a secured storage for key-value pairs. In this implementation,
 * each file stores one key-value pair. Keys are encoded in file names, and
 * values are encrypted with checksums. The encryption key is protected by a
 * user-defined password. To keep things simple, buffers are always larger than
 * the maximum space we needed, so boundary checks on buffers are omitted. */

using ::android::sp;
using ::android::hardware::configureRpcThreadpool;
using ::android::system::wifi::keystore::V1_0::IKeystore;
using ::android::system::wifi::keystore::V1_0::implementation::Keystore;
using ::android::hidl::manager::V1_1::IServiceManager;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::keymaster::V4_0::SecurityLevel;
using ::android::hardware::keymaster::V4_0::HmacSharingParameters;
using ::android::hardware::keymaster::V4_0::ErrorCode;

using ::keystore::keymaster::support::Keymaster;
using ::keystore::keymaster::support::Keymaster3;
using ::keystore::keymaster::support::Keymaster4;

using keystore::KeymasterDevices;

template <typename Wrapper>
KeymasterDevices enumerateKeymasterDevices(IServiceManager* serviceManager) {
    KeymasterDevices result;
    serviceManager->listByInterface(
        Wrapper::WrappedIKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& names) {
            auto try_get_device = [&](const auto& name, bool fail_silent) {
                auto device = Wrapper::WrappedIKeymasterDevice::getService(name);
                if (fail_silent && !device) return;
                CHECK(device) << "Failed to get service for \""
                              << Wrapper::WrappedIKeymasterDevice::descriptor
                              << "\" with interface name \"" << name << "\"";

                sp<Keymaster> kmDevice(new Wrapper(device, name));
                auto halVersion = kmDevice->halVersion();
                SecurityLevel securityLevel = halVersion.securityLevel;
                LOG(INFO) << "found " << Wrapper::WrappedIKeymasterDevice::descriptor
                          << " with interface name " << name << " and seclevel "
                          << toString(securityLevel);
                CHECK(static_cast<uint32_t>(securityLevel) < result.size())
                    << "Security level of \"" << Wrapper::WrappedIKeymasterDevice::descriptor
                    << "\" with interface name \"" << name << "\" out of range";
                auto& deviceSlot = result[securityLevel];
                if (deviceSlot) {
                    if (!fail_silent) {
                        LOG(WARNING) << "Implementation of \""
                                     << Wrapper::WrappedIKeymasterDevice::descriptor
                                     << "\" with interface name \"" << name
                                     << "\" and security level: " << toString(securityLevel)
                                     << " Masked by other implementation of Keymaster";
                    }
                } else {
                    deviceSlot = kmDevice;
                }
            };
            bool has_default = false;
            for (auto& n : names) {
                try_get_device(n, false);
                if (n == "default") has_default = true;
            }
            // Make sure that we always check the default device. If we enumerate only what is
            // known to hwservicemanager, we miss a possible passthrough HAL.
            if (!has_default) {
                try_get_device("default", true /* fail_silent */);
            }
        });
    return result;
}

KeymasterDevices initializeKeymasters() {
    auto serviceManager = android::hidl::manager::V1_1::IServiceManager::getService();
    CHECK(serviceManager.get()) << "Failed to get ServiceManager";
    auto result = enumerateKeymasterDevices<Keymaster4>(serviceManager.get());
    auto softKeymaster = result[SecurityLevel::SOFTWARE];
    if (!result[SecurityLevel::TRUSTED_ENVIRONMENT]) {
        result = enumerateKeymasterDevices<Keymaster3>(serviceManager.get());
    }
    if (softKeymaster) result[SecurityLevel::SOFTWARE] = softKeymaster;
    if (result[SecurityLevel::SOFTWARE] && !result[SecurityLevel::TRUSTED_ENVIRONMENT]) {
        LOG(WARNING) << "No secure Keymaster implementation found, but device offers insecure"
                        " Keymaster HAL. Using as default.";
        result[SecurityLevel::TRUSTED_ENVIRONMENT] = result[SecurityLevel::SOFTWARE];
        result[SecurityLevel::SOFTWARE] = nullptr;
    }
    if (!result[SecurityLevel::SOFTWARE]) {
        auto fbdev = android::keystore::makeSoftwareKeymasterDevice();
        CHECK(fbdev.get()) << "Unable to create Software Keymaster Device";
        result[SecurityLevel::SOFTWARE] = new Keymaster3(fbdev, "Software");
    }
    return result;
}

int main(int argc, char* argv[]) {
    using android::hardware::hidl_string;
    CHECK(argc >= 2) << "A directory must be specified!";
    CHECK(chdir(argv[1]) != -1) << "chdir: " << argv[1] << ": " << strerror(errno);

    auto kmDevices = initializeKeymasters();

    CHECK(kmDevices[SecurityLevel::SOFTWARE]) << "Missing software Keymaster device";
    CHECK(kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT])
        << "Error no viable keymaster device found";

    CHECK(configure_selinux() != -1) << "Failed to configure SELinux.";

    auto halVersion = kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT]->halVersion();

    // If the hardware is keymaster 2.0 or higher we will not allow the fallback device for import
    // or generation of keys. The fallback device is only used for legacy keys present on the
    // device.
    SecurityLevel minimalAllowedSecurityLevelForNewKeys =
        halVersion.majorVersion >= 2 ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE;

    keystore::KeyStore keyStore(kmDevices, minimalAllowedSecurityLevelForNewKeys);
    keyStore.initialize();
    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
    android::sp<keystore::KeyStoreService> service = new keystore::KeyStoreService(&keyStore);
    android::status_t ret = sm->addService(android::String16("android.security.keystore"), service);
    CHECK(ret == android::OK) << "Couldn't register binder service!";

    /**
     * Register the wifi keystore HAL service to run in passthrough mode.
     * This will spawn off a new thread which will service the HIDL
     * transactions.
     */
    configureRpcThreadpool(1, false /* callerWillJoin */);
    android::sp<IKeystore> wifiKeystoreHalService = new Keystore();
    android::status_t err = wifiKeystoreHalService->registerAsService();
    CHECK(ret == android::OK) << "Cannot register wifi keystore HAL service: " << err;

    /*
     * This thread is just going to process Binder transactions.
     */
    android::IPCThreadState::self()->joinThreadPool();
    return 1;
}