diff options
author | Darren Krahn <dkrahn@google.com> | 2016-01-12 08:01:04 -0800 |
---|---|---|
committer | Darren Krahn <dkrahn@google.com> | 2016-02-01 18:07:11 -0800 |
commit | 9caf492818a4cc51ba471534d3fcaa84c9ce0278 (patch) | |
tree | 76215be9020d1975bd13687b21f0b46e73e94482 | |
parent | 0e860e79fefad0327d7256ebf6ea273eeacc8e6f (diff) | |
download | tpm-9caf492818a4cc51ba471534d3fcaa84c9ce0278.tar.gz |
trunks: Create an Android.mk file for trunks and enable binder.
This includes a trunksd.rc file which starts the service as root,
seccomp policies, and a few other changes to get trunks working on
brillo.
BUG=25360556
TEST=unit tests on target
TEST=manual test on all brilloemulator*-eng boards
Change-Id: I9bca71480b7b2c79e0c24c9dc346f225d1d69ef9
42 files changed, 1229 insertions, 362 deletions
diff --git a/trunks/Android.mk b/trunks/Android.mk new file mode 100644 index 0000000..521293d --- /dev/null +++ b/trunks/Android.mk @@ -0,0 +1,206 @@ +# Copyright (C) 2015 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. + +LOCAL_PATH := $(call my-dir) + +# Common variables +# ======================================================== +trunksCppExtension := .cc +trunksCFlags := -Wall -Werror -Wno-unused-parameter -DUSE_BINDER_IPC +trunksIncludes := $(LOCAL_PATH)/.. external/gtest/include +trunksSharedLibraries := \ + libbinder \ + libbinderwrapper \ + libbrillo \ + libbrillo-binder \ + libchrome \ + libchrome-crypto \ + libcrypto \ + libprotobuf-cpp-lite \ + libutils \ + +# libtrunks_generated +# ======================================================== +include $(CLEAR_VARS) +LOCAL_MODULE := libtrunks_generated +LOCAL_MODULE_CLASS := STATIC_LIBRARIES +LOCAL_CPP_EXTENSION := $(trunksCppExtension) +LOCAL_CFLAGS := $(trunksCFlags) +LOCAL_CLANG := true +proto_include := $(call local-generated-sources-dir)/proto/$(LOCAL_PATH)/.. +aidl_include := $(call local-generated-sources-dir)/aidl-generated/include +LOCAL_C_INCLUDES := $(proto_include) $(aidl_include) $(trunksIncludes) +LOCAL_EXPORT_C_INCLUDE_DIRS := $(proto_include) $(aidl_include) +LOCAL_SHARED_LIBRARIES := $(trunksSharedLibraries) +LOCAL_SRC_FILES := \ + interface.proto \ + aidl/android/trunks/ITrunks.aidl \ + aidl/android/trunks/ITrunksClient.aidl \ + +LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl +include $(BUILD_STATIC_LIBRARY) + +# libtrunks_common +# ======================================================== +include $(CLEAR_VARS) +LOCAL_MODULE := libtrunks_common +LOCAL_CPP_EXTENSION := $(trunksCppExtension) +LOCAL_CFLAGS := $(trunksCFlags) +LOCAL_CLANG := true +LOCAL_C_INCLUDES := $(trunksIncludes) +LOCAL_SHARED_LIBRARIES := $(trunksSharedLibraries) +LOCAL_STATIC_LIBRARIES := libtrunks_generated +LOCAL_SRC_FILES := \ + background_command_transceiver.cc \ + blob_parser.cc \ + error_codes.cc \ + hmac_authorization_delegate.cc \ + hmac_session_impl.cc \ + password_authorization_delegate.cc \ + policy_session_impl.cc \ + scoped_key_handle.cc \ + session_manager_impl.cc \ + tpm_generated.cc \ + tpm_state_impl.cc \ + tpm_utility_impl.cc \ + trunks_factory_impl.cc \ + +include $(BUILD_STATIC_LIBRARY) + +# trunksd +# ======================================================== +include $(CLEAR_VARS) +LOCAL_MODULE := trunksd +LOCAL_CPP_EXTENSION := $(trunksCppExtension) +LOCAL_CFLAGS := $(trunksCFlags) +ifeq ($(BRILLOEMULATOR),true) +LOCAL_CFLAGS += -DUSE_SIMULATOR +endif +LOCAL_CLANG := true +ifeq ($(BRILLOEMULATOR),true) +LOCAL_INIT_RC := trunksd-simulator.rc +else +LOCAL_INIT_RC := trunksd.rc +endif +LOCAL_C_INCLUDES := $(trunksIncludes) +LOCAL_SHARED_LIBRARIES := \ + $(trunksSharedLibraries) \ + libbrillo-minijail \ + libminijail \ + +ifeq ($(BRILLOEMULATOR),true) +LOCAL_SHARED_LIBRARIES += libtpm2 +endif +LOCAL_STATIC_LIBRARIES := \ + libtrunks_generated \ + libtrunks_common \ + +LOCAL_REQUIRED_MODULES := \ + com.android.Trunks.conf \ + trunksd-seccomp.policy \ + +LOCAL_SRC_FILES := \ + resource_manager.cc \ + tpm_handle.cc \ + tpm_simulator_handle.cc \ + trunks_binder_service.cc \ + trunksd.cc \ + +include $(BUILD_EXECUTABLE) + +# trunksd-seccomp.policy +# ======================================================== +include $(CLEAR_VARS) +LOCAL_MODULE := trunksd-seccomp.policy +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT)/usr/share/policy/ +LOCAL_SRC_FILES := trunksd-seccomp-$(TARGET_ARCH).policy +include $(BUILD_PREBUILT) + +# libtrunks +# ======================================================== +include $(CLEAR_VARS) +LOCAL_MODULE := libtrunks +LOCAL_CPP_EXTENSION := $(trunksCppExtension) +LOCAL_CFLAGS := $(trunksCFlags) +LOCAL_CLANG := true +LOCAL_C_INCLUDES := $(trunksIncludes) +LOCAL_SHARED_LIBRARIES := $(trunksSharedLibraries) +LOCAL_STATIC_LIBRARIES := \ + libtrunks_common \ + libtrunks_generated \ + +LOCAL_SRC_FILES := \ + trunks_binder_proxy.cc \ + +include $(BUILD_SHARED_LIBRARY) + +# trunks_client +# ======================================================== +include $(CLEAR_VARS) +LOCAL_MODULE := trunks_client +LOCAL_CPP_EXTENSION := $(trunksCppExtension) +LOCAL_CFLAGS := $(trunksCFlags) +LOCAL_CLANG := true +LOCAL_C_INCLUDES := $(trunksIncludes) +LOCAL_SHARED_LIBRARIES := $(trunksSharedLibraries) libtrunks +LOCAL_STATIC_LIBRARIES := libtrunks_common +LOCAL_SRC_FILES := \ + trunks_client.cc \ + trunks_client_test.cc \ + +include $(BUILD_EXECUTABLE) + +# Target unit tests +# ======================================================== +include $(CLEAR_VARS) +LOCAL_MODULE := trunks_test +LOCAL_MODULE_TAGS := debug +LOCAL_CPP_EXTENSION := $(trunksCppExtension) +LOCAL_CFLAGS := $(trunksCFlags) +LOCAL_CLANG := true +LOCAL_C_INCLUDES := $(trunksIncludes) +LOCAL_SHARED_LIBRARIES := $(trunksSharedLibraries) +LOCAL_SRC_FILES := \ + background_command_transceiver_test.cc \ + hmac_authorization_delegate_test.cc \ + hmac_session_test.cc \ + mock_authorization_delegate.cc \ + mock_blob_parser.cc \ + mock_command_transceiver.cc \ + mock_hmac_session.cc \ + mock_policy_session.cc \ + mock_session_manager.cc \ + mock_tpm.cc \ + mock_tpm_state.cc \ + mock_tpm_utility.cc \ + password_authorization_delegate_test.cc \ + policy_session_test.cc \ + resource_manager.cc \ + resource_manager_test.cc \ + scoped_key_handle_test.cc \ + session_manager_test.cc \ + tpm_generated_test.cc \ + tpm_state_test.cc \ + tpm_utility_test.cc \ + trunks_factory_for_test.cc \ + +LOCAL_STATIC_LIBRARIES := \ + libgmock \ + libgtest \ + libBionicGtestMain \ + libtrunks_common \ + libtrunks_generated \ + +include $(BUILD_NATIVE_TEST) diff --git a/trunks/aidl/android/trunks/ITrunks.aidl b/trunks/aidl/android/trunks/ITrunks.aidl new file mode 100644 index 0000000..6d075fe --- /dev/null +++ b/trunks/aidl/android/trunks/ITrunks.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2016 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. + */ + +package android.trunks; + +import android.trunks.ITrunksClient; + +interface ITrunks { + oneway void SendCommand(in byte[] command, in ITrunksClient client); + byte[] SendCommandAndWait(in byte[] command); +} diff --git a/trunks/aidl/android/trunks/ITrunksClient.aidl b/trunks/aidl/android/trunks/ITrunksClient.aidl new file mode 100644 index 0000000..31a0d0b --- /dev/null +++ b/trunks/aidl/android/trunks/ITrunksClient.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2016 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. + */ + +package android.trunks; + +interface ITrunksClient { + oneway void OnCommandResponse(in byte[] response); +} diff --git a/trunks/background_command_transceiver.cc b/trunks/background_command_transceiver.cc index cc96e69..aa18000 100644 --- a/trunks/background_command_transceiver.cc +++ b/trunks/background_command_transceiver.cc @@ -22,6 +22,7 @@ #include <base/logging.h> #include <base/single_thread_task_runner.h> #include <base/synchronization/waitable_event.h> +#include <base/thread_task_runner_handle.h> namespace { diff --git a/trunks/binder_interface.h b/trunks/binder_interface.h new file mode 100644 index 0000000..a9e0fba --- /dev/null +++ b/trunks/binder_interface.h @@ -0,0 +1,26 @@ +// +// Copyright (C) 2014 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. +// + +#ifndef TRUNKS_BINDER_INTERFACE_H_ +#define TRUNKS_BINDER_INTERFACE_H_ + +namespace trunks { + +constexpr char kTrunksServiceName[] = "trunks_service"; + +}; // namespace trunks + +#endif // TRUNKS_BINDER_INTERFACE_H_ diff --git a/trunks/dbus_interface.h b/trunks/dbus_interface.h index e438683..aad78fc 100644 --- a/trunks/dbus_interface.h +++ b/trunks/dbus_interface.h @@ -19,7 +19,7 @@ namespace trunks { -#ifdef __ANDROID__ +#if defined(__ANDROID__) constexpr char kTrunksInterface[] = "com.android.Trunks"; constexpr char kTrunksServicePath[] = "/com/android/Trunks"; constexpr char kTrunksServiceName[] = "com.android.Trunks"; diff --git a/trunks/ftdi/mpsse.c b/trunks/ftdi/mpsse.c index 5171324..b109bb0 100644 --- a/trunks/ftdi/mpsse.c +++ b/trunks/ftdi/mpsse.c @@ -1,19 +1,17 @@ /* -/* -/*Copyright (C) 2015 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. - */ + *Copyright (C) 2015 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. * * This file was copied from https://github.com/devttys0/libmpsse.git (sha1 * f1a6744b), and modified to suite the Chromium OS project. diff --git a/trunks/ftdi/mpsse.h b/trunks/ftdi/mpsse.h index c0c3c9d..f73eede 100644 --- a/trunks/ftdi/mpsse.h +++ b/trunks/ftdi/mpsse.h @@ -1,19 +1,17 @@ /* -/* -/*Copyright (C) 2015 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. - */ + *Copyright (C) 2015 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. * * This file was copied from https://github.com/devttys0/libmpsse.git (sha1 * f1a6744b), and modified to suite the Chromium OS project. diff --git a/trunks/hmac_authorization_delegate_test.cc b/trunks/hmac_authorization_delegate_test.cc index 025c80a..6a4e2e3 100644 --- a/trunks/hmac_authorization_delegate_test.cc +++ b/trunks/hmac_authorization_delegate_test.cc @@ -27,7 +27,7 @@ TEST(HmacAuthorizationDelegateTest, UninitializedSessionTest) { std::string dummy; std::string p_hash("test"); EXPECT_FALSE(delegate.GetCommandAuthorization(p_hash, false, false, &dummy)); - EXPECT_EQ(0, dummy.size()); + EXPECT_EQ(0u, dummy.size()); EXPECT_FALSE(delegate.CheckResponseAuthorization(p_hash, dummy)); EXPECT_FALSE(delegate.EncryptCommandParameter(&dummy)); EXPECT_FALSE(delegate.DecryptResponseParameter(&dummy)); @@ -41,7 +41,7 @@ TEST(HmacAuthorizationDelegateTest, SessionKeyTest) { TPM_HANDLE dummy_handle = HMAC_SESSION_FIRST; EXPECT_TRUE(delegate.InitSession(dummy_handle, nonce, nonce, std::string(), std::string(), false)); - EXPECT_EQ(0, delegate.session_key_.size()); + EXPECT_EQ(0u, delegate.session_key_.size()); std::string dummy_auth = std::string("authorization"); std::string dummy_salt = std::string("salt"); diff --git a/trunks/dbus_interface.proto b/trunks/interface.proto index c38b57a..03797eb 100644 --- a/trunks/dbus_interface.proto +++ b/trunks/interface.proto @@ -1,7 +1,7 @@ option optimize_for = LITE_RUNTIME; package trunks; -// The messages in this file correspond to the trunksd D-Bus interface. Each +// The messages in this file correspond to the trunksd IPC interface. Each // exported method is represented here by a request and response protobuf. // Inputs for the SendCommand method. diff --git a/trunks/policy_session_test.cc b/trunks/policy_session_test.cc index c2d93e8..5d9e8c5 100644 --- a/trunks/policy_session_test.cc +++ b/trunks/policy_session_test.cc @@ -109,7 +109,7 @@ TEST_F(PolicySessionTest, GetDigestSuccess) { .WillOnce(DoAll(SetArgPointee<2>(policy_digest), Return(TPM_RC_SUCCESS))); EXPECT_EQ(TPM_RC_SUCCESS, session.GetDigest(&digest)); - EXPECT_EQ(SHA256_DIGEST_SIZE, digest.size()); + EXPECT_EQ(static_cast<size_t>(SHA256_DIGEST_SIZE), digest.size()); } TEST_F(PolicySessionTest, GetDigestFailure) { @@ -167,7 +167,7 @@ TEST_F(PolicySessionTest, PolicyPCRSuccess) { EXPECT_EQ(TPM_RC_SUCCESS, session.PolicyPCR(pcr_index, pcr_digest)); uint8_t pcr_select_index = pcr_index / 8; uint8_t pcr_select_byte = 1 << (pcr_index % 8); - EXPECT_EQ(pcr_select.count, 1); + EXPECT_EQ(pcr_select.count, 1u); EXPECT_EQ(pcr_select.pcr_selections[0].hash, TPM_ALG_SHA256); EXPECT_EQ(pcr_select.pcr_selections[0].sizeof_select, PCR_SELECT_MIN); EXPECT_EQ(pcr_select.pcr_selections[0].pcr_select[pcr_select_index], diff --git a/trunks/resource_manager.cc b/trunks/resource_manager.cc index 5955d97..82dd18d 100644 --- a/trunks/resource_manager.cc +++ b/trunks/resource_manager.cc @@ -64,15 +64,11 @@ ResourceManager::~ResourceManager() {} void ResourceManager::Initialize() { TPM_RC result = factory_.GetTpm()->StartupSync(TPM_SU_CLEAR, nullptr); // Ignore TPM_RC_INITIALIZE, that means it was already started. - if (result != TPM_RC_SUCCESS && result != TPM_RC_INITIALIZE) { - LOG(ERROR) << "TPM startup failure: " << GetErrorString(result); - exit(-1); - } + CHECK(result == TPM_RC_SUCCESS || result == TPM_RC_INITIALIZE) + << "TPM startup failure: " << GetErrorString(result); result = factory_.GetTpm()->SelfTestSync(YES /* Full test. */, nullptr); - if (result != TPM_RC_SUCCESS) { - LOG(ERROR) << "TPM self-test failure: " << GetErrorString(result); - exit(-1); - } + CHECK_EQ(result, TPM_RC_SUCCESS) << "TPM self-test failure: " + << GetErrorString(result); // Full control of the TPM is assumed and required. Existing transient object // and session handles are mercilessly flushed. for (UINT32 handle_type : {HR_TRANSIENT, diff --git a/trunks/resource_manager_test.cc b/trunks/resource_manager_test.cc index 5d2f43e..4aafbaf 100644 --- a/trunks/resource_manager_test.cc +++ b/trunks/resource_manager_test.cc @@ -230,7 +230,9 @@ class ResourceManagerTest : public testing::Test { // Creates a TPMS_CONTEXT with the given sequence field. TPMS_CONTEXT CreateContext(UINT64 sequence) { - TPMS_CONTEXT context = {sequence}; + TPMS_CONTEXT context; + memset(&context, 0, sizeof(context)); + context.sequence = sequence; return context; } @@ -756,7 +758,7 @@ TEST_F(ResourceManagerTest, ExternalContext) { EXPECT_EQ(context_save_response1, actual_response); // Invoke a context gap (which will cause context1 to be mapped to context2). - EXPECT_CALL(tpm_, ContextLoadSync(Field(&TPMS_CONTEXT::sequence, Eq(1)), + EXPECT_CALL(tpm_, ContextLoadSync(Field(&TPMS_CONTEXT::sequence, Eq(1u)), _, _)) .WillOnce(Return(TPM_RC_SUCCESS)); EXPECT_CALL(tpm_, ContextSaveSync(kArbitrarySessionHandle, _, _, _)) diff --git a/trunks/scoped_key_handle_test.cc b/trunks/scoped_key_handle_test.cc index 2d91917..3f40be6 100644 --- a/trunks/scoped_key_handle_test.cc +++ b/trunks/scoped_key_handle_test.cc @@ -65,7 +65,7 @@ TEST_F(ScopedKeyHandleTest, ReleaseTest) { TPM_HANDLE handle = TPM_RH_FIRST; ScopedKeyHandle scoped_handle(factory_, handle); EXPECT_EQ(handle, scoped_handle.release()); - EXPECT_EQ(0, scoped_handle.get()); + EXPECT_EQ(0u, scoped_handle.get()); } TEST_F(ScopedKeyHandleTest, ResetAndFlush) { @@ -88,7 +88,7 @@ TEST_F(ScopedKeyHandleTest, NullReset) { EXPECT_CALL(mock_tpm_, FlushContextSync(handle, _)) .WillOnce(Return(TPM_RC_SUCCESS)); scoped_handle.reset(); - EXPECT_EQ(0, scoped_handle.get()); + EXPECT_EQ(0u, scoped_handle.get()); } } // namespace trunks diff --git a/trunks/session_manager_impl.cc b/trunks/session_manager_impl.cc index f1a648f..9370ec9 100644 --- a/trunks/session_manager_impl.cc +++ b/trunks/session_manager_impl.cc @@ -24,6 +24,7 @@ #include <crypto/scoped_openssl_types.h> #include <openssl/err.h> #include <openssl/evp.h> +#include <openssl/mem.h> #include <openssl/rand.h> #include <openssl/rsa.h> @@ -83,7 +84,7 @@ TPM_RC SessionManagerImpl::StartSession( reinterpret_cast<unsigned char*>(string_as_array(&salt)); CHECK_EQ(RAND_bytes(salt_buffer, salt.size()), 1) << "Error generating a cryptographically random salt."; - // First we enccrypt the cryptographically secure salt using PKCS1_OAEP + // First we encrypt the cryptographically secure salt using PKCS1_OAEP // padded RSA public key encryption. This is specified in TPM2.0 // Part1 Architecture, Appendix B.10.2. std::string encrypted_salt; diff --git a/trunks/session_manager_test.cc b/trunks/session_manager_test.cc index 4b38835..eb99331 100644 --- a/trunks/session_manager_test.cc +++ b/trunks/session_manager_test.cc @@ -18,10 +18,12 @@ #include <vector> +#include <base/logging.h> #include <base/strings/string_number_conversions.h> #include <gmock/gmock.h> #include <gtest/gtest.h> +#include "trunks/error_codes.h" #include "trunks/mock_tpm.h" #include "trunks/tpm_generated.h" #include "trunks/tpm_utility.h" @@ -60,7 +62,7 @@ class SessionManagerTest : public testing::Test { "D3C74E721ACA97F7ADBE2CCF7B4BCC165F7380F48065F2C8370F25F066091259" "D14EA362BAF236E3CD8771A94BDEDA3900577143A238AB92B6C55F11DEFAFB31" "7D1DC5B6AE210C52B008D87F2A7BFF6EB5C4FB32D6ECEC6505796173951A3167"; - std::vector<uint8> bytes; + std::vector<uint8_t> bytes; CHECK(base::HexStringToBytes(kValidModulus, &bytes)); CHECK_EQ(bytes.size(), 256u); TPM2B_PUBLIC_KEY_RSA rsa; @@ -126,9 +128,9 @@ TEST_F(SessionManagerTest, StartSessionBadSaltingKey) { EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, nullptr)) .WillOnce(DoAll(SetArgPointee<2>(public_data), Return(TPM_RC_SUCCESS))); - EXPECT_EQ(TPM_RC_FAILURE, session_manager_.StartSession(TPM_SE_TRIAL, - TPM_RH_NULL, "", - false, delegate_)); + EXPECT_EQ(TRUNKS_RC_SESSION_SETUP_ERROR, + session_manager_.StartSession(TPM_SE_TRIAL, TPM_RH_NULL, "", false, + delegate_)); } TEST_F(SessionManagerTest, StartSessionFailure) { diff --git a/trunks/tpm_generated_test.cc b/trunks/tpm_generated_test.cc index 6a7e15e..6048153 100644 --- a/trunks/tpm_generated_test.cc +++ b/trunks/tpm_generated_test.cc @@ -54,14 +54,14 @@ TEST(GeneratorTest, SerializeParseStruct) { std::string buffer; TPM_RC rc = Serialize_TPM2B_CREATION_DATA(data, &buffer); ASSERT_EQ(TPM_RC_SUCCESS, rc); - EXPECT_EQ(35, buffer.size()); + EXPECT_EQ(35u, buffer.size()); TPM2B_CREATION_DATA data2; memset(&data2, 0, sizeof(TPM2B_CREATION_DATA)); std::string buffer_before = buffer; std::string buffer_parsed; rc = Parse_TPM2B_CREATION_DATA(&buffer, &data2, &buffer_parsed); ASSERT_EQ(TPM_RC_SUCCESS, rc); - EXPECT_EQ(0, buffer.size()); + EXPECT_EQ(0u, buffer.size()); EXPECT_EQ(buffer_before, buffer_parsed); EXPECT_EQ(buffer_before.size() - 2, data2.size); EXPECT_EQ(0, memcmp(&data.creation_data, @@ -81,7 +81,7 @@ TEST(GeneratorTest, ParseBufferOverflow) { // Case 1: Sufficient source but overflow the destination. std::string malformed1 = "\x10\x00"; malformed1 += std::string(0x1000, 'A'); - ASSERT_GT(0x1000, sizeof(tmp.buffer)); + ASSERT_GT(0x1000u, sizeof(tmp.buffer)); EXPECT_EQ(TPM_RC_INSUFFICIENT, Parse_TPM2B_MAX_BUFFER(&malformed1, &tmp, nullptr)); // Case 2: Sufficient destination but overflow the source. @@ -249,7 +249,7 @@ TEST(GeneratorTest, SynchronousCommandResponseTest) { EXPECT_EQ(creation_hash.size, 1); EXPECT_EQ(creation_hash.buffer[0], 'b'); EXPECT_EQ(creation_ticket.tag, 0x8002); - EXPECT_EQ(creation_ticket.hierarchy, 0x40000007); + EXPECT_EQ(creation_ticket.hierarchy, 0x40000007u); EXPECT_EQ(creation_ticket.digest.size, 0); EXPECT_EQ(key_name.size, 3); EXPECT_EQ(key_name.name[0], 'K'); diff --git a/trunks/tpm_simulator_handle.cc b/trunks/tpm_simulator_handle.cc index 4402a95..0ef8210 100644 --- a/trunks/tpm_simulator_handle.cc +++ b/trunks/tpm_simulator_handle.cc @@ -18,7 +18,7 @@ #include <unistd.h> -#ifdef USE_SIMULATOR +#if defined(USE_SIMULATOR) extern "C" { #include <tpm2/TpmBuildSwitches.h> #include <tpm2/_TPM_Init_fp.h> @@ -41,7 +41,7 @@ TpmSimulatorHandle::TpmSimulatorHandle() {} TpmSimulatorHandle::~TpmSimulatorHandle() {} bool TpmSimulatorHandle::Init() { -#ifdef USE_SIMULATOR +#if defined(USE_SIMULATOR) // Initialize TPM. CHECK_EQ(chdir("/data/misc/trunksd"), 0); _plat__Signal_PowerOn(); @@ -61,7 +61,7 @@ void TpmSimulatorHandle::SendCommand(const std::string& command, } std::string TpmSimulatorHandle::SendCommandAndWait(const std::string& command) { -#ifdef USE_SIMULATOR +#if defined(USE_SIMULATOR) unsigned int response_size; unsigned char* response; std::string mutable_command(command); diff --git a/trunks/tpm_state_test.cc b/trunks/tpm_state_test.cc index 5833607..8bf4f39 100644 --- a/trunks/tpm_state_test.cc +++ b/trunks/tpm_state_test.cc @@ -195,10 +195,10 @@ TEST_F(TpmStateTest, FlagsClear) { EXPECT_FALSE(tpm_state.WasShutdownOrderly()); EXPECT_FALSE(tpm_state.IsRSASupported()); EXPECT_FALSE(tpm_state.IsECCSupported()); - EXPECT_EQ(0, tpm_state.GetLockoutCounter()); - EXPECT_EQ(0, tpm_state.GetLockoutThreshold()); - EXPECT_EQ(0, tpm_state.GetLockoutInterval()); - EXPECT_EQ(0, tpm_state.GetLockoutRecovery()); + EXPECT_EQ(0u, tpm_state.GetLockoutCounter()); + EXPECT_EQ(0u, tpm_state.GetLockoutThreshold()); + EXPECT_EQ(0u, tpm_state.GetLockoutInterval()); + EXPECT_EQ(0u, tpm_state.GetLockoutRecovery()); } TEST_F(TpmStateTest, FlagsSet) { diff --git a/trunks/tpm_utility_impl.cc b/trunks/tpm_utility_impl.cc index c99beb6..b3e0756 100644 --- a/trunks/tpm_utility_impl.cc +++ b/trunks/tpm_utility_impl.cc @@ -215,7 +215,6 @@ TPM_RC TpmUtilityImpl::AllocatePCR(const std::string& platform_password) { ++pcr_allocation.count; } for (auto pcr_type : pcr_banks_to_remove) { - memset(&pcr_allocation, 0, sizeof(pcr_allocation)); pcr_allocation.pcr_selections[pcr_allocation.count].hash = pcr_type; pcr_allocation.pcr_selections[pcr_allocation.count].sizeof_select = PCR_SELECT_MAX; diff --git a/trunks/tpm_utility_test.cc b/trunks/tpm_utility_test.cc index 18436ba..a245cdd 100644 --- a/trunks/tpm_utility_test.cc +++ b/trunks/tpm_utility_test.cc @@ -86,6 +86,56 @@ class TpmUtilityTest : public testing::Test { return utility_.CreateSaltingKey(owner_password); } + void SetExistingKeyHandleExpectation(TPM_HANDLE handle) { + TPMS_CAPABILITY_DATA capability_data = {}; + TPML_HANDLE& handles = capability_data.data.handles; + handles.count = 1; + handles.handle[0] = handle; + EXPECT_CALL(mock_tpm_, + GetCapabilitySync(TPM_CAP_HANDLES, handle, _, _, _, _)) + .WillRepeatedly( + DoAll(SetArgPointee<4>(capability_data), Return(TPM_RC_SUCCESS))); + } + + void PopulatePCRSelection(bool has_sha1_pcrs, + bool make_sha1_bank_empty, + bool has_sha256_pcrs, + TPML_PCR_SELECTION* pcrs) { + memset(pcrs, 0, sizeof(TPML_PCR_SELECTION)); + // By convention fill SHA-256 first. This is a bit brittle because order is + // not important but it simplifies comparison to memcmp. + if (has_sha256_pcrs) { + pcrs->pcr_selections[pcrs->count].hash = TPM_ALG_SHA256; + pcrs->pcr_selections[pcrs->count].sizeof_select = PCR_SELECT_MIN; + for (int i = 0; i < PCR_SELECT_MIN; ++i) { + pcrs->pcr_selections[pcrs->count].pcr_select[i] = 0xff; + } + ++pcrs->count; + } + if (has_sha1_pcrs) { + pcrs->pcr_selections[pcrs->count].hash = TPM_ALG_SHA1; + if (make_sha1_bank_empty) { + pcrs->pcr_selections[pcrs->count].sizeof_select = PCR_SELECT_MAX; + } else { + pcrs->pcr_selections[pcrs->count].sizeof_select = PCR_SELECT_MIN; + for (int i = 0; i < PCR_SELECT_MIN; ++i) { + pcrs->pcr_selections[pcrs->count].pcr_select[i] = 0xff; + } + } + ++pcrs->count; + } + } + + void SetExistingPCRSExpectation(bool has_sha1_pcrs, bool has_sha256_pcrs) { + TPMS_CAPABILITY_DATA capability_data = {}; + TPML_PCR_SELECTION& pcrs = capability_data.data.assigned_pcr; + PopulatePCRSelection(has_sha1_pcrs, false, has_sha256_pcrs, &pcrs); + EXPECT_CALL(mock_tpm_, + GetCapabilitySync(TPM_CAP_PCRS, _, _, _, _, _)) + .WillRepeatedly( + DoAll(SetArgPointee<4>(capability_data), Return(TPM_RC_SUCCESS))); + } + protected: TrunksFactoryForTest factory_; NiceMock<MockBlobParser> mock_blob_parser_; @@ -142,18 +192,18 @@ TEST_F(TpmUtilityTest, ShutdownTest) { } TEST_F(TpmUtilityTest, InitializeTpmAlreadyInit) { + SetExistingPCRSExpectation(false, true); EXPECT_EQ(TPM_RC_SUCCESS, utility_.InitializeTpm()); EXPECT_EQ(TPM_RC_SUCCESS, utility_.InitializeTpm()); } TEST_F(TpmUtilityTest, InitializeTpmSuccess) { - EXPECT_CALL(mock_tpm_, PCR_AllocateSync(_, _, _, _, _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<3>(YES), - Return(TPM_RC_SUCCESS))); + SetExistingPCRSExpectation(false, true); EXPECT_EQ(TPM_RC_SUCCESS, utility_.InitializeTpm()); } TEST_F(TpmUtilityTest, InitializeTpmBadAuth) { + SetExistingPCRSExpectation(false, true); // Reject attempts to set platform auth. EXPECT_CALL(mock_tpm_, HierarchyChangeAuthSync(TPM_RH_PLATFORM, _, _, _)) .WillRepeatedly(Return(TPM_RC_FAILURE)); @@ -161,36 +211,74 @@ TEST_F(TpmUtilityTest, InitializeTpmBadAuth) { } TEST_F(TpmUtilityTest, InitializeTpmDisablePHFails) { - EXPECT_CALL(mock_tpm_, PCR_AllocateSync(_, _, _, _, _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<3>(YES), - Return(TPM_RC_SUCCESS))); + SetExistingPCRSExpectation(false, true); // Reject attempts to disable the platform hierarchy. EXPECT_CALL(mock_tpm_, HierarchyControlSync(_, _, TPM_RH_PLATFORM, _, _)) .WillRepeatedly(Return(TPM_RC_FAILURE)); EXPECT_EQ(TPM_RC_FAILURE, utility_.InitializeTpm()); } -TEST_F(TpmUtilityTest, AllocatePCRSuccess) { - TPML_PCR_SELECTION pcr_allocation; +TEST_F(TpmUtilityTest, AllocatePCRFromNone) { + SetExistingPCRSExpectation(false, false); + TPML_PCR_SELECTION new_pcr_allocation; EXPECT_CALL(mock_tpm_, PCR_AllocateSync(TPM_RH_PLATFORM, _, _, _, _, _, _, _)) - .WillOnce(DoAll(SaveArg<2>(&pcr_allocation), + .WillOnce(DoAll(SaveArg<2>(&new_pcr_allocation), SetArgPointee<3>(YES), Return(TPM_RC_SUCCESS))); - EXPECT_EQ(TPM_RC_SUCCESS, utility_.AllocatePCR("")); - EXPECT_EQ(1, pcr_allocation.count); - EXPECT_EQ(TPM_ALG_SHA256, pcr_allocation.pcr_selections[0].hash); - EXPECT_EQ(PCR_SELECT_MIN, pcr_allocation.pcr_selections[0].sizeof_select); - EXPECT_EQ(0xFF, pcr_allocation.pcr_selections[0].pcr_select[0]); - EXPECT_EQ(0xFF, pcr_allocation.pcr_selections[0].pcr_select[1]); + ASSERT_EQ(TPM_RC_SUCCESS, utility_.AllocatePCR("")); + ASSERT_EQ(1u, new_pcr_allocation.count); + TPML_PCR_SELECTION expected_pcr_allocation; + PopulatePCRSelection(false, false, true, &expected_pcr_allocation); + ASSERT_EQ(0, memcmp(&expected_pcr_allocation, &new_pcr_allocation, + sizeof(TPML_PCR_SELECTION))); +} + +TEST_F(TpmUtilityTest, AllocatePCRFromSHA1Only) { + SetExistingPCRSExpectation(true, false); + TPML_PCR_SELECTION new_pcr_allocation; + EXPECT_CALL(mock_tpm_, PCR_AllocateSync(TPM_RH_PLATFORM, _, _, _, _, _, _, _)) + .WillOnce(DoAll(SaveArg<2>(&new_pcr_allocation), + SetArgPointee<3>(YES), + Return(TPM_RC_SUCCESS))); + ASSERT_EQ(TPM_RC_SUCCESS, utility_.AllocatePCR("")); + ASSERT_EQ(2u, new_pcr_allocation.count); + TPML_PCR_SELECTION expected_pcr_allocation; + PopulatePCRSelection(true, true, true, &expected_pcr_allocation); + ASSERT_EQ(0, memcmp(&expected_pcr_allocation, &new_pcr_allocation, + sizeof(TPML_PCR_SELECTION))); +} + +TEST_F(TpmUtilityTest, AllocatePCRFromSHA1AndSHA256) { + SetExistingPCRSExpectation(true, true); + TPML_PCR_SELECTION new_pcr_allocation; + EXPECT_CALL(mock_tpm_, PCR_AllocateSync(TPM_RH_PLATFORM, _, _, _, _, _, _, _)) + .WillOnce(DoAll(SaveArg<2>(&new_pcr_allocation), + SetArgPointee<3>(YES), + Return(TPM_RC_SUCCESS))); + ASSERT_EQ(TPM_RC_SUCCESS, utility_.AllocatePCR("")); + ASSERT_EQ(1u, new_pcr_allocation.count); + TPML_PCR_SELECTION expected_pcr_allocation; + PopulatePCRSelection(true, true, false, &expected_pcr_allocation); + ASSERT_EQ(0, memcmp(&expected_pcr_allocation, &new_pcr_allocation, + sizeof(TPML_PCR_SELECTION))); +} + +TEST_F(TpmUtilityTest, AllocatePCRFromSHA256Only) { + SetExistingPCRSExpectation(false, true); + EXPECT_CALL(mock_tpm_, PCR_AllocateSync(TPM_RH_PLATFORM, _, _, _, _, _, _, _)) + .Times(0); + ASSERT_EQ(TPM_RC_SUCCESS, utility_.AllocatePCR("")); } TEST_F(TpmUtilityTest, AllocatePCRCommandFailure) { + SetExistingPCRSExpectation(false, false); EXPECT_CALL(mock_tpm_, PCR_AllocateSync(_, _, _, _, _, _, _, _)) .WillOnce(Return(TPM_RC_FAILURE)); EXPECT_EQ(TPM_RC_FAILURE, utility_.AllocatePCR("")); } TEST_F(TpmUtilityTest, AllocatePCRTpmFailure) { + SetExistingPCRSExpectation(false, false); EXPECT_CALL(mock_tpm_, PCR_AllocateSync(_, _, _, _, _, _, _, _)) .WillOnce(DoAll(SetArgPointee<3>(NO), Return(TPM_RC_SUCCESS))); @@ -306,7 +394,7 @@ TEST_F(TpmUtilityTest, GenerateRandomSuccess) { // This number is larger than the max bytes the GetRandom call can return. // Therefore we expect software to make multiple calls to fill this many // bytes. - int num_bytes = 72; + size_t num_bytes = 72; std::string random_data; TPM2B_DIGEST large_random; large_random.size = 32; @@ -325,7 +413,7 @@ TEST_F(TpmUtilityTest, GenerateRandomSuccess) { } TEST_F(TpmUtilityTest, GenerateRandomFails) { - int num_bytes = 5; + size_t num_bytes = 5; std::string random_data; EXPECT_CALL(mock_tpm_, GetRandomSync(_, _, nullptr)) .WillOnce(Return(TPM_RC_FAILURE)); @@ -342,7 +430,7 @@ TEST_F(TpmUtilityTest, ExtendPCRSuccess) { Return(TPM_RC_SUCCESS))); EXPECT_EQ(TPM_RC_SUCCESS, utility_.ExtendPCR(1, "test digest", &mock_authorization_delegate_)); - EXPECT_EQ(1, digests.count); + EXPECT_EQ(1u, digests.count); EXPECT_EQ(TPM_ALG_SHA256, digests.digests[0].hash_alg); std::string hash_string = crypto::SHA256HashString("test digest"); EXPECT_EQ(0, memcmp(hash_string.data(), @@ -447,7 +535,7 @@ TEST_F(TpmUtilityTest, AsymmetricEncryptFail) { } TEST_F(TpmUtilityTest, AsymmetricEncryptBadParams) { - TPM_HANDLE key_handle; + TPM_HANDLE key_handle = TPM_RH_FIRST; std::string plaintext; std::string ciphertext; TPM2B_PUBLIC public_area; @@ -579,11 +667,9 @@ TEST_F(TpmUtilityTest, AsymmetricDecryptFail) { } TEST_F(TpmUtilityTest, AsymmetricDecryptBadParams) { - TPM_HANDLE key_handle; - std::string key_name; + TPM_HANDLE key_handle = TPM_RH_FIRST; std::string plaintext; std::string ciphertext; - std::string password; TPM2B_PUBLIC public_area; public_area.public_area.type = TPM_ALG_RSA; public_area.public_area.object_attributes = kDecrypt | kRestricted; @@ -1297,13 +1383,13 @@ TEST_F(TpmUtilityTest, CreateRSAKeyPairSuccess) { EXPECT_EQ(public_area.public_area.object_attributes & kSign, kSign); EXPECT_EQ(public_area.public_area.object_attributes & kUserWithAuth, kUserWithAuth); - EXPECT_EQ(public_area.public_area.object_attributes & kAdminWithPolicy, 0); + EXPECT_EQ(public_area.public_area.object_attributes & kAdminWithPolicy, 0u); EXPECT_EQ(public_area.public_area.parameters.rsa_detail.scheme.scheme, TPM_ALG_NULL); - EXPECT_EQ(1, creation_pcrs.count); + EXPECT_EQ(1u, creation_pcrs.count); EXPECT_EQ(TPM_ALG_SHA256, creation_pcrs.pcr_selections[0].hash); EXPECT_EQ(PCR_SELECT_MIN, creation_pcrs.pcr_selections[0].sizeof_select); - EXPECT_EQ(1 << (creation_pcr % 8), + EXPECT_EQ(1u << (creation_pcr % 8), creation_pcrs.pcr_selections[0].pcr_select[creation_pcr / 8]); } @@ -1320,7 +1406,7 @@ TEST_F(TpmUtilityTest, CreateRSAKeyPairDecryptKeySuccess) { "", false, kNoCreationPCR, &mock_authorization_delegate_, &key_blob, nullptr)); EXPECT_EQ(public_area.public_area.object_attributes & kDecrypt, kDecrypt); - EXPECT_EQ(public_area.public_area.object_attributes & kSign, 0); + EXPECT_EQ(public_area.public_area.object_attributes & kSign, 0u); EXPECT_EQ(public_area.public_area.parameters.rsa_detail.scheme.scheme, TPM_ALG_NULL); } @@ -1341,15 +1427,15 @@ TEST_F(TpmUtilityTest, CreateRSAKeyPairSignKeySuccess) { TpmUtility::AsymmetricKeyUsage::kSignKey, 2048, 0x10001, key_auth, policy_digest, true /* use_only_policy_authorization */, kNoCreationPCR, &mock_authorization_delegate_, &key_blob, nullptr)); - EXPECT_EQ(public_area.public_area.object_attributes & kDecrypt, 0); + EXPECT_EQ(public_area.public_area.object_attributes & kDecrypt, 0u); EXPECT_EQ(public_area.public_area.object_attributes & kSign, kSign); - EXPECT_EQ(public_area.public_area.object_attributes & kUserWithAuth, 0); + EXPECT_EQ(public_area.public_area.object_attributes & kUserWithAuth, 0u); EXPECT_EQ(public_area.public_area.object_attributes & kAdminWithPolicy, kAdminWithPolicy); EXPECT_EQ(public_area.public_area.parameters.rsa_detail.scheme.scheme, TPM_ALG_NULL); EXPECT_EQ(public_area.public_area.parameters.rsa_detail.key_bits, 2048); - EXPECT_EQ(public_area.public_area.parameters.rsa_detail.exponent, 0x10001); + EXPECT_EQ(public_area.public_area.parameters.rsa_detail.exponent, 0x10001u); EXPECT_EQ(public_area.public_area.auth_policy.size, policy_digest.size()); EXPECT_EQ(0, memcmp(public_area.public_area.auth_policy.buffer, policy_digest.data(), policy_digest.size())); @@ -1897,17 +1983,11 @@ TEST_F(TpmUtilityTest, SetKnownPasswordFailure) { } TEST_F(TpmUtilityTest, RootKeysSuccess) { - EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _)) - .Times(2) - .WillRepeatedly(Return(TPM_RC_FAILURE)); EXPECT_EQ(TPM_RC_SUCCESS, CreateStorageRootKeys("password")); } TEST_F(TpmUtilityTest, RootKeysHandleConsistency) { TPM_HANDLE test_handle = 42; - EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _)) - .Times(2) - .WillRepeatedly(Return(TPM_RC_FAILURE)); EXPECT_CALL(mock_tpm_, CreatePrimarySyncShort(_, _, _, _, _, _, _, _, _, _)) .WillRepeatedly(DoAll(SetArgPointee<3>(test_handle), Return(TPM_RC_SUCCESS))); @@ -1917,33 +1997,24 @@ TEST_F(TpmUtilityTest, RootKeysHandleConsistency) { } TEST_F(TpmUtilityTest, RootKeysCreateFailure) { - EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _)) - .WillRepeatedly(Return(TPM_RC_FAILURE)); EXPECT_CALL(mock_tpm_, CreatePrimarySyncShort(_, _, _, _, _, _, _, _, _, _)) .WillRepeatedly(Return(TPM_RC_FAILURE)); EXPECT_EQ(TPM_RC_FAILURE, CreateStorageRootKeys("password")); } TEST_F(TpmUtilityTest, RootKeysPersistFailure) { - EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _)) - .WillRepeatedly(Return(TPM_RC_FAILURE)); EXPECT_CALL(mock_tpm_, EvictControlSync(_, _, _, _, _, _)) .WillRepeatedly(Return(TPM_RC_FAILURE)); EXPECT_EQ(TPM_RC_FAILURE, CreateStorageRootKeys("password")); } TEST_F(TpmUtilityTest, RootKeysAlreadyExist) { - EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _)) - .Times(2) - .WillRepeatedly(Return(TPM_RC_SUCCESS)); + SetExistingKeyHandleExpectation(kRSAStorageRootKey); + SetExistingKeyHandleExpectation(kECCStorageRootKey); EXPECT_EQ(TPM_RC_SUCCESS, CreateStorageRootKeys("password")); } TEST_F(TpmUtilityTest, SaltingKeySuccess) { - EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _)) - .WillOnce(Return(TPM_RC_SUCCESS)); - EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, _)) - .WillOnce(Return(TPM_RC_FAILURE)); TPM2B_PUBLIC public_area; EXPECT_CALL(mock_tpm_, CreateSyncShort(_, _, _, _, _, _, _, _, _, _)) .WillOnce(DoAll(SaveArg<2>(&public_area), @@ -1953,10 +2024,6 @@ TEST_F(TpmUtilityTest, SaltingKeySuccess) { } TEST_F(TpmUtilityTest, SaltingKeyConsistency) { - EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _)) - .WillOnce(Return(TPM_RC_SUCCESS)); - EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, _)) - .WillOnce(Return(TPM_RC_FAILURE)); TPM_HANDLE test_handle = 42; EXPECT_CALL(mock_tpm_, LoadSync(_, _, _, _, _, _, _)) .WillRepeatedly(DoAll(SetArgPointee<4>(test_handle), @@ -1967,38 +2034,25 @@ TEST_F(TpmUtilityTest, SaltingKeyConsistency) { } TEST_F(TpmUtilityTest, SaltingKeyCreateFailure) { - EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _)) - .WillOnce(Return(TPM_RC_SUCCESS)); - EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, _)) - .WillOnce(Return(TPM_RC_FAILURE)); EXPECT_CALL(mock_tpm_, CreateSyncShort(_, _, _, _, _, _, _, _, _, _)) .WillRepeatedly(Return(TPM_RC_FAILURE)); EXPECT_EQ(TPM_RC_FAILURE, CreateSaltingKey("password")); } TEST_F(TpmUtilityTest, SaltingKeyLoadFailure) { - EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _)) - .WillOnce(Return(TPM_RC_SUCCESS)); - EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, _)) - .WillOnce(Return(TPM_RC_FAILURE)); EXPECT_CALL(mock_tpm_, LoadSync(_, _, _, _, _, _, _)) .WillRepeatedly(Return(TPM_RC_FAILURE)); EXPECT_EQ(TPM_RC_FAILURE, CreateSaltingKey("password")); } TEST_F(TpmUtilityTest, SaltingKeyPersistFailure) { - EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _)) - .WillOnce(Return(TPM_RC_SUCCESS)); - EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, _)) - .WillOnce(Return(TPM_RC_FAILURE)); EXPECT_CALL(mock_tpm_, EvictControlSync(_, _, _, _, _, _)) .WillRepeatedly(Return(TPM_RC_FAILURE)); EXPECT_EQ(TPM_RC_FAILURE, CreateSaltingKey("password")); } TEST_F(TpmUtilityTest, SaltingKeyAlreadyExists) { - EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, _)) - .WillOnce(Return(TPM_RC_SUCCESS)); + SetExistingKeyHandleExpectation(kSaltingKey); EXPECT_EQ(TPM_RC_SUCCESS, CreateSaltingKey("password")); } diff --git a/trunks/trunks_binder_proxy.cc b/trunks/trunks_binder_proxy.cc new file mode 100644 index 0000000..772afc7 --- /dev/null +++ b/trunks/trunks_binder_proxy.cc @@ -0,0 +1,121 @@ +// +// Copyright (C) 2016 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 "trunks/trunks_binder_proxy.h" + +#include <base/bind.h> +#include <base/callback.h> +#include <base/logging.h> +#include <binderwrapper/binder_wrapper.h> +#include <utils/Errors.h> + +#include "android/trunks/BnTrunksClient.h" +#include "android/trunks/BpTrunks.h" +#include "trunks/binder_interface.h" +#include "trunks/error_codes.h" +#include "trunks/interface.pb.h" + +namespace { + +// Implements ITrunksClient and forwards response data to a ResponseCallback. +class ResponseObserver : public android::trunks::BnTrunksClient { + public: + ResponseObserver(const trunks::CommandTransceiver::ResponseCallback& callback) + : callback_(callback) {} + + // ITrunksClient interface. + android::binder::Status OnCommandResponse( + const std::vector<int8_t>& response_proto_data) override { + trunks::SendCommandResponse response_proto; + if (!response_proto.ParseFromArray(response_proto_data.data(), + response_proto_data.size())) { + LOG(ERROR) << "TrunksBinderProxy: Bad response data."; + callback_.Run( + trunks::CreateErrorResponse(trunks::SAPI_RC_MALFORMED_RESPONSE)); + } + callback_.Run(response_proto.response()); + return android::binder::Status::ok(); + } + + private: + trunks::CommandTransceiver::ResponseCallback callback_; +}; + +} // namespace + +namespace trunks { + +bool TrunksBinderProxy::Init() { + android::sp<android::IBinder> service_binder = + android::BinderWrapper::GetOrCreateInstance()->GetService( + kTrunksServiceName); + if (!service_binder.get()) { + LOG(ERROR) << "TrunksBinderProxy: Trunks service does not exist."; + return false; + } + trunks_service_ = new android::trunks::BpTrunks(service_binder); + return true; +} + +void TrunksBinderProxy::SendCommand(const std::string& command, + const ResponseCallback& callback) { + SendCommandRequest command_proto; + command_proto.set_command(command); + std::vector<int8_t> command_proto_data; + command_proto_data.resize(command_proto.ByteSize()); + if (!command_proto.SerializeToArray(command_proto_data.data(), + command_proto_data.size())) { + LOG(ERROR) << "TrunksBinderProxy: Failed to serialize protobuf."; + callback.Run(CreateErrorResponse(TRUNKS_RC_IPC_ERROR)); + return; + } + android::sp<ResponseObserver> observer(new ResponseObserver(callback)); + android::binder::Status status = + trunks_service_->SendCommand(command_proto_data, observer); + if (!status.isOk()) { + LOG(ERROR) << "TrunksBinderProxy: Binder error: " << status.toString8(); + callback.Run(CreateErrorResponse(TRUNKS_RC_IPC_ERROR)); + return; + } +} + +std::string TrunksBinderProxy::SendCommandAndWait(const std::string& command) { + SendCommandRequest command_proto; + command_proto.set_command(command); + std::vector<int8_t> command_proto_data; + command_proto_data.resize(command_proto.ByteSize()); + if (!command_proto.SerializeToArray(command_proto_data.data(), + command_proto_data.size())) { + LOG(ERROR) << "TrunksBinderProxy: Failed to serialize protobuf."; + return CreateErrorResponse(TRUNKS_RC_IPC_ERROR); + } + std::vector<int8_t> response_proto_data; + android::binder::Status status = trunks_service_->SendCommandAndWait( + command_proto_data, &response_proto_data); + if (!status.isOk()) { + LOG(ERROR) << "TrunksBinderProxy: Binder error: " << status.toString8(); + return CreateErrorResponse(TRUNKS_RC_IPC_ERROR); + } + trunks::SendCommandResponse response_proto; + if (!response_proto.ParseFromArray(response_proto_data.data(), + response_proto_data.size())) { + LOG(ERROR) << "TrunksBinderProxy: Bad response data."; + return trunks::CreateErrorResponse(trunks::SAPI_RC_MALFORMED_RESPONSE); + } + return response_proto.response(); +} + +} // namespace trunks diff --git a/trunks/trunks_binder_proxy.h b/trunks/trunks_binder_proxy.h new file mode 100644 index 0000000..359094a --- /dev/null +++ b/trunks/trunks_binder_proxy.h @@ -0,0 +1,53 @@ +// +// Copyright (C) 2016 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. +// + +#ifndef TRUNKS_TRUNKS_BINDER_PROXY_H_ +#define TRUNKS_TRUNKS_BINDER_PROXY_H_ + +#include <string> + +#include "android/trunks/ITrunks.h" +#include "trunks/command_transceiver.h" +#include "trunks/trunks_export.h" + +namespace trunks { + +// TrunksBinderProxy is a CommandTransceiver implementation that forwards all +// commands to the trunksd binder daemon. See TrunksBinderService for details on +// how the commands are handled once they reach trunksd. +class TRUNKS_EXPORT TrunksBinderProxy : public CommandTransceiver { + public: + TrunksBinderProxy() = default; + ~TrunksBinderProxy() override = default; + + // Initializes the client. Returns true on success. + bool Init() override; + + // Asynchronous calls assume a message loop and binder watcher have already + // been configured elsewhere. + void SendCommand(const std::string& command, + const ResponseCallback& callback) override; + std::string SendCommandAndWait(const std::string& command) override; + + private: + android::sp<android::trunks::ITrunks> trunks_service_; + + DISALLOW_COPY_AND_ASSIGN(TrunksBinderProxy); +}; + +} // namespace trunks + +#endif // TRUNKS_TRUNKS_BINDER_PROXY_H_ diff --git a/trunks/trunks_binder_service.cc b/trunks/trunks_binder_service.cc new file mode 100644 index 0000000..028aa3c --- /dev/null +++ b/trunks/trunks_binder_service.cc @@ -0,0 +1,120 @@ +// +// Copyright (C) 2016 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 "trunks/trunks_binder_service.h" + +#include <sysexits.h> + +#include <base/bind.h> +#include <binderwrapper/binder_wrapper.h> + +#include "trunks/binder_interface.h" +#include "trunks/command_transceiver.h" +#include "trunks/error_codes.h" +#include "trunks/interface.pb.h" + +namespace { + +// If |command| is a valid command protobuf, provides the |command_data| and +// returns true. Otherwise, returns false. +bool ParseCommandProto(const std::vector<int8_t>& command, + std::string* command_data) { + trunks::SendCommandRequest request_proto; + if (!request_proto.ParseFromArray(command.data(), command.size()) || + !request_proto.has_command() || request_proto.command().empty()) { + return false; + } + *command_data = request_proto.command(); + return true; +} + +void CreateResponseProto(const std::string& data, + std::vector<int8_t>* response) { + trunks::SendCommandResponse response_proto; + response_proto.set_response(data); + response->resize(response_proto.ByteSize()); + CHECK(response_proto.SerializeToArray(response->data(), response->size())) + << "TrunksBinderService: Failed to serialize protobuf."; +} + +} // namespace + +namespace trunks { + +int TrunksBinderService::OnInit() { + android::BinderWrapper::Create(); + if (!watcher_.Init()) { + LOG(ERROR) << "TrunksBinderService: BinderWatcher::Init failed."; + return EX_UNAVAILABLE; + } + binder_ = new BinderServiceInternal(this); + if (!android::BinderWrapper::Get()->RegisterService( + kTrunksServiceName, android::IInterface::asBinder(binder_))) { + LOG(ERROR) << "TrunksBinderService: RegisterService failed."; + return EX_UNAVAILABLE; + } + LOG(INFO) << "Trunks: Binder service registered."; + return brillo::Daemon::OnInit(); +} + +TrunksBinderService::BinderServiceInternal::BinderServiceInternal( + TrunksBinderService* service) + : service_(service) {} + +android::binder::Status TrunksBinderService::BinderServiceInternal::SendCommand( + const std::vector<int8_t>& command, + const android::sp<android::trunks::ITrunksClient>& client) { + auto callback = + base::Bind(&TrunksBinderService::BinderServiceInternal::OnResponse, + GetWeakPtr(), client); + std::string command_data; + if (!ParseCommandProto(command, &command_data)) { + LOG(ERROR) << "TrunksBinderService: Bad command data."; + callback.Run(CreateErrorResponse(SAPI_RC_BAD_PARAMETER)); + return android::binder::Status::ok(); + } + service_->transceiver_->SendCommand(command_data, callback); + return android::binder::Status::ok(); +} + +void TrunksBinderService::BinderServiceInternal::OnResponse( + const android::sp<android::trunks::ITrunksClient>& client, + const std::string& response) { + std::vector<int8_t> binder_response; + CreateResponseProto(response, &binder_response); + android::binder::Status status = client->OnCommandResponse(binder_response); + if (!status.isOk()) { + LOG(ERROR) << "TrunksBinderService: Failed to send response to client: " + << status.toString8(); + } +} + +android::binder::Status +TrunksBinderService::BinderServiceInternal::SendCommandAndWait( + const std::vector<int8_t>& command, + std::vector<int8_t>* response) { + std::string command_data; + if (!ParseCommandProto(command, &command_data)) { + LOG(ERROR) << "TrunksBinderService: Bad command data."; + CreateResponseProto(CreateErrorResponse(SAPI_RC_BAD_PARAMETER), response); + return android::binder::Status::ok(); + } + CreateResponseProto(service_->transceiver_->SendCommandAndWait(command_data), + response); + return android::binder::Status::ok(); +} + +} // namespace trunks diff --git a/trunks/trunks_binder_service.h b/trunks/trunks_binder_service.h new file mode 100644 index 0000000..7f809ac --- /dev/null +++ b/trunks/trunks_binder_service.h @@ -0,0 +1,90 @@ +// +// Copyright (C) 2016 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. +// + +#ifndef TRUNKS_TRUNKS_BINDER_SERVICE_H_ +#define TRUNKS_TRUNKS_BINDER_SERVICE_H_ + +#include <base/memory/weak_ptr.h> +#include <brillo/binder_watcher.h> +#include <brillo/daemons/daemon.h> + +#include "android/trunks/BnTrunks.h" +#include "trunks/command_transceiver.h" + +namespace trunks { + +// TrunksBinderService registers for and handles all incoming binder calls for +// the trunksd system daemon. +// +// Example Usage: +// +// TrunksBinderService service; +// service.set_transceiver(&my_transceiver); +// service.Run(); +class TrunksBinderService : public brillo::Daemon { + public: + TrunksBinderService() = default; + ~TrunksBinderService() override = default; + + // The |transceiver| will be the target of all incoming TPM commands. This + // class does not take ownership of |transceiver|. + void set_transceiver(CommandTransceiver* transceiver) { + transceiver_ = transceiver; + } + + protected: + int OnInit() override; + + private: + friend class BinderServiceInternal; + class BinderServiceInternal : public android::trunks::BnTrunks { + public: + BinderServiceInternal(TrunksBinderService* service); + ~BinderServiceInternal() override = default; + + // ITrunks interface. + android::binder::Status SendCommand( + const std::vector<int8_t>& command, + const android::sp<android::trunks::ITrunksClient>& client) override; + android::binder::Status SendCommandAndWait( + const std::vector<int8_t>& command, + std::vector<int8_t>* response) override; + + private: + void OnResponse(const android::sp<android::trunks::ITrunksClient>& client, + const std::string& response); + + base::WeakPtr<BinderServiceInternal> GetWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + + TrunksBinderService* service_; + + // Declared last so weak pointers are invalidated first on destruction. + base::WeakPtrFactory<BinderServiceInternal> weak_factory_{this}; + }; + + CommandTransceiver* transceiver_ = nullptr; + brillo::BinderWatcher watcher_; + android::sp<BinderServiceInternal> binder_; + + DISALLOW_COPY_AND_ASSIGN(TrunksBinderService); +}; + +} // namespace trunks + + +#endif // TRUNKS_TRUNKS_BINDER_SERVICE_H_ diff --git a/trunks/trunks_client.cc b/trunks/trunks_client.cc index 4975470..ac29bf1 100644 --- a/trunks/trunks_client.cc +++ b/trunks/trunks_client.cc @@ -33,7 +33,6 @@ #include "trunks/tpm_utility.h" #include "trunks/trunks_client_test.h" #include "trunks/trunks_factory_impl.h" -#include "trunks/trunks_proxy.h" namespace { @@ -143,14 +142,8 @@ int main(int argc, char **argv) { return 0; } - CommandTransceiver* proxy = new trunks::TrunksProxy(); - - if (!proxy->Init()) { - LOG(ERROR) << "Error initializing proxy to communicate with TPM."; - return -1; - } scoped_ptr<TrunksFactory> factory = scoped_ptr<TrunksFactory>( - new trunks::TrunksFactoryImpl(proxy)); + new trunks::TrunksFactoryImpl(true /* failure_is_fatal */)); if (cl->HasSwitch("status")) { return DumpStatus(factory.get()); diff --git a/trunks/trunks_client_test.cc b/trunks/trunks_client_test.cc index 594747a..fc78b19 100644 --- a/trunks/trunks_client_test.cc +++ b/trunks/trunks_client_test.cc @@ -57,7 +57,8 @@ std::string GetOpenSSLError() { namespace trunks { -TrunksClientTest::TrunksClientTest() : factory_(new TrunksFactoryImpl()) { +TrunksClientTest::TrunksClientTest() + : factory_(new TrunksFactoryImpl(true /* failure_is_fatal */)) { crypto::EnsureOpenSSLInit(); } @@ -987,7 +988,7 @@ bool TrunksClientTest::PerformRSAEncrpytAndDecrpyt( void TrunksClientTest::GenerateRSAKeyPair(std::string* modulus, std::string* prime_factor, std::string* public_key) { -#ifdef OPENSSL_IS_BORINGSSL +#if defined(OPENSSL_IS_BORINGSSL) crypto::ScopedRSA rsa(RSA_new()); crypto::ScopedBIGNUM exponent(BN_new()); CHECK(BN_set_word(exponent.get(), RSA_F4)); diff --git a/trunks/trunks_proxy.cc b/trunks/trunks_dbus_proxy.cc index ddef65b..9c2dfae 100644 --- a/trunks/trunks_proxy.cc +++ b/trunks/trunks_dbus_proxy.cc @@ -14,15 +14,15 @@ // limitations under the License. // -#include "trunks/trunks_proxy.h" +#include "trunks/trunks_dbus_proxy.h" #include <base/bind.h> #include <brillo/bind_lambda.h> #include <brillo/dbus/dbus_method_invoker.h> #include "trunks/dbus_interface.h" -#include "trunks/dbus_interface.pb.h" #include "trunks/error_codes.h" +#include "trunks/interface.pb.h" namespace { @@ -36,15 +36,15 @@ const int kDBusMaxTimeout = 5 * 60 * 1000; namespace trunks { -TrunksProxy::TrunksProxy() : weak_factory_(this) {} +TrunksDBusProxy::TrunksDBusProxy() : weak_factory_(this) {} -TrunksProxy::~TrunksProxy() { +TrunksDBusProxy::~TrunksDBusProxy() { if (bus_) { bus_->ShutdownAndBlock(); } } -bool TrunksProxy::Init() { +bool TrunksDBusProxy::Init() { dbus::Bus::Options options; options.bus_type = dbus::Bus::SYSTEM; bus_ = new dbus::Bus(options); @@ -55,10 +55,10 @@ bool TrunksProxy::Init() { return (object_proxy_ != nullptr); } -void TrunksProxy::SendCommand(const std::string& command, +void TrunksDBusProxy::SendCommand(const std::string& command, const ResponseCallback& callback) { if (origin_thread_id_ != base::PlatformThread::CurrentId()) { - LOG(ERROR) << "Error TrunksProxy cannot be shared by multiple threads."; + LOG(ERROR) << "Error TrunksDBusProxy cannot be shared by multiple threads."; callback.Run(CreateErrorResponse(TRUNKS_RC_IPC_ERROR)); } SendCommandRequest tpm_command_proto; @@ -81,9 +81,9 @@ void TrunksProxy::SendCommand(const std::string& command, tpm_command_proto); } -std::string TrunksProxy::SendCommandAndWait(const std::string& command) { +std::string TrunksDBusProxy::SendCommandAndWait(const std::string& command) { if (origin_thread_id_ != base::PlatformThread::CurrentId()) { - LOG(ERROR) << "Error TrunksProxy cannot be shared by multiple threads."; + LOG(ERROR) << "Error TrunksDBusProxy cannot be shared by multiple threads."; return CreateErrorResponse(TRUNKS_RC_IPC_ERROR); } SendCommandRequest tpm_command_proto; diff --git a/trunks/trunks_proxy.h b/trunks/trunks_dbus_proxy.h index 858b1ea..aa60e63 100644 --- a/trunks/trunks_proxy.h +++ b/trunks/trunks_dbus_proxy.h @@ -14,10 +14,8 @@ // limitations under the License. // -#ifndef TRUNKS_TRUNKS_PROXY_H_ -#define TRUNKS_TRUNKS_PROXY_H_ - -#include "trunks/command_transceiver.h" +#ifndef TRUNKS_TRUNKS_DBUS_PROXY_H_ +#define TRUNKS_TRUNKS_DBUS_PROXY_H_ #include <string> @@ -26,18 +24,19 @@ #include <dbus/bus.h> #include <dbus/object_proxy.h> +#include "trunks/command_transceiver.h" #include "trunks/trunks_export.h" namespace trunks { -// TrunksProxy is a CommandTransceiver implementation that forwards all commands -// to the trunksd D-Bus daemon. See TrunksService for details on how the -// commands are handled once they reach trunksd. TrunksProxy must be used in -// only one thread. -class TRUNKS_EXPORT TrunksProxy: public CommandTransceiver { +// TrunksDBusProxy is a CommandTransceiver implementation that forwards all +// commands to the trunksd D-Bus daemon. See TrunksDBusService for details on +// how the commands are handled once they reach trunksd. A TrunksDBusProxy +// instance must be used in only one thread. +class TRUNKS_EXPORT TrunksDBusProxy: public CommandTransceiver { public: - TrunksProxy(); - ~TrunksProxy() override; + TrunksDBusProxy(); + ~TrunksDBusProxy() override; // Initializes the D-Bus client. Returns true on success. bool Init() override; @@ -48,7 +47,7 @@ class TRUNKS_EXPORT TrunksProxy: public CommandTransceiver { std::string SendCommandAndWait(const std::string& command) override; private: - base::WeakPtr<TrunksProxy> GetWeakPtr() { + base::WeakPtr<TrunksDBusProxy> GetWeakPtr() { return weak_factory_.GetWeakPtr(); } @@ -57,11 +56,11 @@ class TRUNKS_EXPORT TrunksProxy: public CommandTransceiver { dbus::ObjectProxy* object_proxy_; // Declared last so weak pointers are invalidated first on destruction. - base::WeakPtrFactory<TrunksProxy> weak_factory_; + base::WeakPtrFactory<TrunksDBusProxy> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(TrunksProxy); + DISALLOW_COPY_AND_ASSIGN(TrunksDBusProxy); }; } // namespace trunks -#endif // TRUNKS_TRUNKS_PROXY_H_ +#endif // TRUNKS_TRUNKS_DBUS_PROXY_H_ diff --git a/trunks/trunks_service.cc b/trunks/trunks_dbus_service.cc index f1aa34e..23a266e 100644 --- a/trunks/trunks_service.cc +++ b/trunks/trunks_dbus_service.cc @@ -14,42 +14,43 @@ // limitations under the License. // -#include "trunks/trunks_service.h" +#include "trunks/trunks_dbus_service.h" #include <base/bind.h> #include <brillo/bind_lambda.h> #include "trunks/dbus_interface.h" -#include "trunks/dbus_interface.pb.h" #include "trunks/error_codes.h" +#include "trunks/interface.pb.h" namespace trunks { +using brillo::dbus_utils::AsyncEventSequencer; using brillo::dbus_utils::DBusMethodResponse; -TrunksService::TrunksService(const scoped_refptr<dbus::Bus>& bus, - CommandTransceiver* transceiver) - : trunks_dbus_object_(nullptr, bus, dbus::ObjectPath(kTrunksServicePath)), - transceiver_(transceiver), - weak_factory_(this) {} +TrunksDBusService::TrunksDBusService() + : brillo::DBusServiceDaemon(trunks::kTrunksServiceName) {} -void TrunksService::Register(const CompletionAction& callback) { +void TrunksDBusService::RegisterDBusObjectsAsync( + AsyncEventSequencer* sequencer) { + trunks_dbus_object_.reset(new brillo::dbus_utils::DBusObject( + nullptr, bus_, dbus::ObjectPath(kTrunksServicePath))); brillo::dbus_utils::DBusInterface* dbus_interface = - trunks_dbus_object_.AddOrGetInterface(kTrunksInterface); - dbus_interface->AddMethodHandler(kSendCommand, - base::Unretained(this), - &TrunksService::HandleSendCommand); - trunks_dbus_object_.RegisterAsync(callback); + trunks_dbus_object_->AddOrGetInterface(kTrunksInterface); + dbus_interface->AddMethodHandler(kSendCommand, base::Unretained(this), + &TrunksDBusService::HandleSendCommand); + trunks_dbus_object_->RegisterAsync( + sequencer->GetHandler("Failed to register D-Bus object.", true)); } -void TrunksService::HandleSendCommand( - std::unique_ptr<DBusMethodResponse< - const SendCommandResponse&>> response_sender, +void TrunksDBusService::HandleSendCommand( + std::unique_ptr<DBusMethodResponse<const SendCommandResponse&>> + response_sender, const SendCommandRequest& request) { // Convert |response_sender| to a shared_ptr so |transceiver_| can safely // copy the callback. - using SharedResponsePointer = std::shared_ptr< - DBusMethodResponse<const SendCommandResponse&>>; + using SharedResponsePointer = + std::shared_ptr<DBusMethodResponse<const SendCommandResponse&>>; // A callback that constructs the response protobuf and sends it. auto callback = [](const SharedResponsePointer& response, const std::string& response_from_tpm) { @@ -58,7 +59,7 @@ void TrunksService::HandleSendCommand( response->Return(tpm_response_proto); }; if (!request.has_command() || request.command().empty()) { - LOG(ERROR) << "TrunksService: Invalid request."; + LOG(ERROR) << "TrunksDBusService: Invalid request."; callback(SharedResponsePointer(std::move(response_sender)), CreateErrorResponse(SAPI_RC_BAD_PARAMETER)); return; diff --git a/trunks/trunks_dbus_service.h b/trunks/trunks_dbus_service.h new file mode 100644 index 0000000..5a7a697 --- /dev/null +++ b/trunks/trunks_dbus_service.h @@ -0,0 +1,79 @@ +// +// Copyright (C) 2016 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. +// + +#ifndef TRUNKS_TRUNKS_DBUS_SERVICE_H_ +#define TRUNKS_TRUNKS_DBUS_SERVICE_H_ + +#include <memory> +#include <string> + +#include <base/memory/weak_ptr.h> +#include <brillo/daemons/dbus_daemon.h> +#include <brillo/dbus/dbus_method_response.h> +#include <brillo/dbus/dbus_object.h> + +#include "trunks/command_transceiver.h" +#include "trunks/interface.pb.h" + +namespace trunks { + +// TrunksDBusService registers for and handles all incoming D-Bus messages for +// the trunksd system daemon. +// +// Example Usage: +// +// TrunksDBusService service; +// service.set_transceiver(&my_transceiver); +// service.Run(); +class TrunksDBusService : public brillo::DBusServiceDaemon { + public: + TrunksDBusService(); + ~TrunksDBusService() override = default; + + // The |transceiver| will be the target of all incoming TPM commands. This + // class does not take ownership of |transceiver|. + void set_transceiver(CommandTransceiver* transceiver) { + transceiver_ = transceiver; + } + + protected: + // Exports D-Bus methods. + void RegisterDBusObjectsAsync( + brillo::dbus_utils::AsyncEventSequencer* sequencer) override; + + private: + // Handles calls to the 'SendCommand' method. + void HandleSendCommand( + std::unique_ptr<brillo::dbus_utils::DBusMethodResponse< + const SendCommandResponse&>> response_sender, + const SendCommandRequest& request); + + base::WeakPtr<TrunksDBusService> GetWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + + std::unique_ptr<brillo::dbus_utils::DBusObject> trunks_dbus_object_; + CommandTransceiver* transceiver_ = nullptr; + + // Declared last so weak pointers are invalidated first on destruction. + base::WeakPtrFactory<TrunksDBusService> weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(TrunksDBusService); +}; + +} // namespace trunks + + +#endif // TRUNKS_TRUNKS_DBUS_SERVICE_H_ diff --git a/trunks/trunks_factory.h b/trunks/trunks_factory.h index b90baa6..92046cf 100644 --- a/trunks/trunks_factory.h +++ b/trunks/trunks_factory.h @@ -28,6 +28,7 @@ namespace trunks { class AuthorizationDelegate; class BlobParser; +class CommandTransceiver; class HmacSession; class PolicySession; class SessionManager; diff --git a/trunks/trunks_factory_impl.cc b/trunks/trunks_factory_impl.cc index 935aba8..8b832c4 100644 --- a/trunks/trunks_factory_impl.cc +++ b/trunks/trunks_factory_impl.cc @@ -16,6 +16,8 @@ #include "trunks/trunks_factory_impl.h" +#include <base/logging.h> + #include "trunks/blob_parser.h" #include "trunks/hmac_session_impl.h" #include "trunks/password_authorization_delegate.h" @@ -24,16 +26,28 @@ #include "trunks/tpm_generated.h" #include "trunks/tpm_state_impl.h" #include "trunks/tpm_utility_impl.h" -#include "trunks/trunks_proxy.h" +#if defined(USE_BINDER_IPC) +#include "trunks/trunks_binder_proxy.h" +#else +#include "trunks/trunks_dbus_proxy.h" +#endif namespace trunks { -TrunksFactoryImpl::TrunksFactoryImpl() { - default_transceiver_.reset(new TrunksProxy()); +TrunksFactoryImpl::TrunksFactoryImpl(bool failure_is_fatal) { +#if defined(USE_BINDER_IPC) + default_transceiver_.reset(new TrunksBinderProxy()); +#else + default_transceiver_.reset(new TrunksDBusProxy()); +#endif transceiver_ = default_transceiver_.get(); tpm_.reset(new Tpm(transceiver_)); if (!transceiver_->Init()) { - LOG(ERROR) << "Error initializing transceiver."; + if (failure_is_fatal) { + LOG(FATAL) << "Error initializing default IPC proxy."; + } else { + LOG(ERROR) << "Error initializing default IPC proxy."; + } } } diff --git a/trunks/trunks_factory_impl.h b/trunks/trunks_factory_impl.h index 084aab7..03d25bf 100644 --- a/trunks/trunks_factory_impl.h +++ b/trunks/trunks_factory_impl.h @@ -30,13 +30,13 @@ namespace trunks { class Tpm; -class TrunksProxy; // TrunksFactoryImpl is the default TrunksFactory implementation. class TRUNKS_EXPORT TrunksFactoryImpl : public TrunksFactory { public: - // Uses TrunksProxy as the default CommandTransceiver to pass to the TPM. - TrunksFactoryImpl(); + // Uses an IPC proxy as the default CommandTransceiver. If |failure_is_fatal| + // is set then a failure to initialize the proxy will abort. + explicit TrunksFactoryImpl(bool failure_is_fatal); // TrunksFactoryImpl does not take ownership of |transceiver|. This // transceiver is forwarded down to the Tpm instance maintained by // this factory. diff --git a/trunks/trunks_service.h b/trunks/trunks_service.h deleted file mode 100644 index 94ea16f..0000000 --- a/trunks/trunks_service.h +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright (C) 2014 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. -// - -#ifndef TRUNKS_TRUNKS_SERVICE_H_ -#define TRUNKS_TRUNKS_SERVICE_H_ - -#include <string> - -#include <base/memory/weak_ptr.h> -#include <brillo/dbus/dbus_method_response.h> -#include <brillo/dbus/dbus_object.h> - -#include "trunks/dbus_interface.pb.h" -#include "trunks/tpm_handle.h" - -namespace trunks { - -using CompletionAction = - brillo::dbus_utils::AsyncEventSequencer::CompletionAction; - -// TrunksService registers for and handles all incoming D-Bus messages for the -// trunksd system daemon. -class TrunksService { - public: - // The |transceiver| will be the target of all incoming TPM commands. - TrunksService(const scoped_refptr<dbus::Bus>& bus, - CommandTransceiver* transceiver); - virtual ~TrunksService() = default; - - // Connects to D-Bus system bus and exports Trunks methods. - void Register(const CompletionAction& callback); - - private: - // Handles calls to the 'SendCommand' method. - void HandleSendCommand( - std::unique_ptr<brillo::dbus_utils::DBusMethodResponse< - const SendCommandResponse&>> response_sender, - const SendCommandRequest& request); - - base::WeakPtr<TrunksService> GetWeakPtr() { - return weak_factory_.GetWeakPtr(); - } - - brillo::dbus_utils::DBusObject trunks_dbus_object_; - CommandTransceiver* transceiver_; - - // Declared last so weak pointers are invalidated first on destruction. - base::WeakPtrFactory<TrunksService> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(TrunksService); -}; - -} // namespace trunks - - -#endif // TRUNKS_TRUNKS_SERVICE_H_ diff --git a/trunks/trunksd-seccomp-arm.policy b/trunks/trunksd-seccomp-arm.policy index 80af7a6..40b0c1a 100644 --- a/trunks/trunksd-seccomp-arm.policy +++ b/trunks/trunksd-seccomp-arm.policy @@ -14,7 +14,6 @@ # limitations under the License. # -# Tested on daisy gettid: 1 getuid32: 1 geteuid32: 1 @@ -27,28 +26,24 @@ clock_getres: 1 clock_gettime: 1 gettimeofday: 1 -socket: arg0 == 0x1 || arg0 == 0x10 -socketpair: 1 -connect: 1 -getsockname: 1 -pipe: 1 -send: 1 -sendmsg: 1 -recvmsg: 1 - -epoll_create: 1 -epoll_wait: 1 +epoll_create1: 1 +epoll_pwait: 1 epoll_ctl: 1 -poll: 1 +openat: 1 read: 1 write: 1 +writev: 1 close: 1 - fstat64: 1 -stat64: 1 _llseek: 1 +lseek: 1 fcntl64: 1 +readlinkat: 1 +faccessat: 1 +pipe2: 1 +socket: 1 +connect: 1 futex: 1 @@ -56,7 +51,27 @@ restart_syscall: 1 exit: 1 exit_group: 1 rt_sigreturn: 1 +sigaltstack: 1 +personality: 1 brk: 1 mmap2: 1 munmap: 1 +madvise: 1 + +# Allow thread creation. +mprotect: 1 +clone: 1 +set_robust_list: 1 +# This is attempted but apparently not necessary; return EPERM. +prctl: return 1 +gettid: 1 +set_tid_address: 1 + +rt_sigprocmask: 1 +signalfd4: 1 +ioctl: 1 +getpriority: 1 +exit: 1 +exit_group: 1 +chdir: 1 diff --git a/trunks/trunksd-seccomp-amd64.policy b/trunks/trunksd-seccomp-arm64.policy index 225e2ed..7581d3c 100644 --- a/trunks/trunksd-seccomp-amd64.policy +++ b/trunks/trunksd-seccomp-arm64.policy @@ -14,7 +14,6 @@ # limitations under the License. # -# Tested on lumpy gettid: 1 getuid: 1 geteuid: 1 @@ -26,31 +25,25 @@ getresgid: 1 clock_getres: 1 clock_gettime: 1 gettimeofday: 1 -time: 1 -# Allow socket(domain==PF_LOCAL) or socket(domain==PF_NETLINK) -socket: arg0 == 0x1 || arg0 == 0x10 -socketpair: 1 -connect: 1 -getsockname: 1 -pipe: 1 -sendmsg: 1 -sendto: 1 -recvmsg: 1 - -epoll_create: 1 -epoll_wait: 1 +epoll_create1: 1 +epoll_pwait: 1 epoll_ctl: 1 -poll: 1 +openat: 1 read: 1 write: 1 +writev: 1 close: 1 - fstat: 1 -stat: 1 lseek: 1 fcntl: 1 +readlinkat: 1 +faccessat: 1 +pipe2: 1 +socket: 1 +connect: 1 +sendto: 1 futex: 1 @@ -58,10 +51,13 @@ restart_syscall: 1 exit: 1 exit_group: 1 rt_sigreturn: 1 +sigaltstack: 1 +personality: 1 brk: 1 mmap: 1 munmap: 1 +madvise: 1 # Allow thread creation. mprotect: 1 @@ -69,6 +65,13 @@ clone: 1 set_robust_list: 1 # This is attempted but apparently not necessary; return EPERM. prctl: return 1 +gettid: 1 +set_tid_address: 1 rt_sigprocmask: 1 signalfd4: 1 +ioctl: 1 +getpriority: 1 +exit: 1 +exit_group: 1 +chdir: 1 diff --git a/trunks/trunksd-seccomp-x86.policy b/trunks/trunksd-seccomp-x86.policy index 3c5495d..575ccb8 100644 --- a/trunks/trunksd-seccomp-x86.policy +++ b/trunks/trunksd-seccomp-x86.policy @@ -14,7 +14,6 @@ # limitations under the License. # -# Tested on alex board gettid: 1 getuid32: 1 geteuid32: 1 @@ -28,18 +27,28 @@ clock_gettime: 1 gettimeofday: 1 time: 1 +epoll_create: 1 +epoll_create1: 1 +epoll_wait: 1 +epoll_pwait: 1 +epoll_ctl: 1 +poll: 1 + +openat: 1 read: 1 write: 1 +writev: 1 close: 1 - -brk: 1 -mmap2: 1 -munmap: 1 - fstat64: 1 +fstatat64: 1 stat64: 1 _llseek: 1 +lseek: 1 fcntl64: 1 +readlinkat: 1 +faccessat: 1 +pipe2: 1 +socketcall: 1 futex: 1 @@ -47,8 +56,29 @@ restart_syscall: 1 exit: 1 exit_group: 1 rt_sigreturn: 1 +sigaltstack: 1 +sigaction: 1 +personality: 1 -epoll_create: 1 -epoll_wait: 1 -epoll_ctl: 1 -poll: 1 +brk: 1 +mmap2: 1 +munmap: 1 +madvise: 1 + +# Allow thread creation. +mprotect: 1 +clone: 1 +set_robust_list: 1 +# This is attempted but apparently not necessary; return EPERM. +prctl: return 1 +set_thread_area: 1 +gettid: 1 +set_tid_address: 1 + +rt_sigprocmask: 1 +signalfd4: 1 +ioctl: 1 +getpriority: 1 +exit: 1 +exit_group: 1 +chdir: 1 diff --git a/trunks/trunksd-seccomp-x86_64.policy b/trunks/trunksd-seccomp-x86_64.policy new file mode 100644 index 0000000..aa8650b --- /dev/null +++ b/trunks/trunksd-seccomp-x86_64.policy @@ -0,0 +1,83 @@ +# +# Copyright (C) 2014 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. +# + +gettid: 1 +getuid: 1 +geteuid: 1 +getgid: 1 +getegid: 1 +getresuid: 1 +getresgid: 1 + +clock_getres: 1 +clock_gettime: 1 +gettimeofday: 1 +time: 1 + +epoll_create: 1 +epoll_create1: 1 +epoll_wait: 1 +epoll_pwait: 1 +epoll_ctl: 1 +poll: 1 + +openat: 1 +read: 1 +write: 1 +writev: 1 +close: 1 +fstat: 1 +stat: 1 +lseek: 1 +fcntl: 1 +readlinkat: 1 +faccessat: 1 +pipe2: 1 +socket: 1 +connect: 1 + +futex: 1 + +restart_syscall: 1 +exit: 1 +exit_group: 1 +rt_sigaction: 1 +rt_sigreturn: 1 +sigaltstack: 1 +personality: 1 + +brk: 1 +mmap: 1 +munmap: 1 +madvise: 1 + +# Allow thread creation. +mprotect: 1 +clone: 1 +set_robust_list: 1 +# This is attempted but apparently not necessary; return EPERM. +prctl: return 1 +set_thread_area: 1 +gettid: 1 +set_tid_address: 1 + +rt_sigprocmask: 1 +signalfd4: 1 +ioctl: 1 +getpriority: 1 +exit: 1 +exit_group: 1 +chdir: 1 diff --git a/trunks/trunksd-simulator.rc b/trunks/trunksd-simulator.rc new file mode 100644 index 0000000..4ac8ca9 --- /dev/null +++ b/trunks/trunksd-simulator.rc @@ -0,0 +1,8 @@ +on post-fs-data + mkdir /data/misc/trunksd 0700 system system + +service trunksd /system/bin/trunksd --simulator + class late_start + user root + group root + oneshot diff --git a/trunks/trunksd.cc b/trunks/trunksd.cc index 4eb7f05..ae3c3fd 100644 --- a/trunks/trunksd.cc +++ b/trunks/trunksd.cc @@ -20,28 +20,35 @@ #include <base/bind.h> #include <base/command_line.h> #include <base/threading/thread.h> -#include <brillo/daemons/dbus_daemon.h> #include <brillo/minijail/minijail.h> #include <brillo/syslog_logging.h> #include <brillo/userdb_utils.h> #include "trunks/background_command_transceiver.h" -#include "trunks/dbus_interface.h" #include "trunks/resource_manager.h" #include "trunks/tpm_handle.h" #include "trunks/tpm_simulator_handle.h" +#if defined(USE_BINDER_IPC) +#include "trunks/trunks_binder_service.h" +#else +#include "trunks/trunks_dbus_service.h" +#endif #include "trunks/trunks_factory_impl.h" #include "trunks/trunks_ftdi_spi.h" -#include "trunks/trunks_service.h" - -using brillo::dbus_utils::AsyncEventSequencer; namespace { const uid_t kRootUID = 0; +#if defined(__ANDROID__) +const char kTrunksUser[] = "system"; +const char kTrunksGroup[] = "system"; +const char kTrunksSeccompPath[] = + "/system/usr/share/policy/trunksd-seccomp.policy"; +#else const char kTrunksUser[] = "trunks"; const char kTrunksGroup[] = "trunks"; const char kTrunksSeccompPath[] = "/usr/share/policy/trunksd-seccomp.policy"; +#endif const char kBackgroundThreadName[] = "trunksd_background_thread"; void InitMinijailSandbox() { @@ -49,7 +56,7 @@ void InitMinijailSandbox() { gid_t trunks_gid; CHECK(brillo::userdb::GetUserInfo(kTrunksUser, &trunks_uid, &trunks_gid)) << "Error getting trunks uid and gid."; - CHECK_EQ(getuid(), kRootUID) << "Trunks Daemon not initialized as root."; + CHECK_EQ(getuid(), kRootUID) << "trunksd not initialized as root."; brillo::Minijail* minijail = brillo::Minijail::GetInstance(); struct minijail* jail = minijail->New(); minijail->DropRoot(jail, kTrunksUser, kTrunksGroup); @@ -57,59 +64,13 @@ void InitMinijailSandbox() { minijail->Enter(jail); minijail->Destroy(jail); CHECK_EQ(getuid(), trunks_uid) - << "TrunksDaemon was not able to drop to trunks user."; + << "trunksd was not able to drop user privilege."; CHECK_EQ(getgid(), trunks_gid) - << "TrunksDaemon was not able to drop to trunks group."; + << "trunksd was not able to drop group privilege."; } } // namespace -class TrunksDaemon : public brillo::DBusServiceDaemon { - public: - explicit TrunksDaemon(trunks::CommandTransceiver* transceiver) : - brillo::DBusServiceDaemon(trunks::kTrunksServiceName) { - transceiver_.reset(transceiver); - background_thread_.reset(new base::Thread(kBackgroundThreadName)); - CHECK(background_thread_->Start()); - // Chain together command transceivers: - // [IPC] --> TrunksService --> BackgroundCommandTransceiver --> - // ResourceManager --> TpmHandle --> [TPM] - factory_.reset(new trunks::TrunksFactoryImpl(transceiver_.get())); - resource_manager_.reset(new trunks::ResourceManager( - *factory_, - transceiver_.get())); - background_thread_->task_runner()->PostNonNestableTask( - FROM_HERE, - base::Bind(&trunks::ResourceManager::Initialize, - base::Unretained(resource_manager_.get()))); - background_transceiver_.reset( - new trunks::BackgroundCommandTransceiver( - resource_manager_.get(), - background_thread_->task_runner())); - } - - protected: - void RegisterDBusObjectsAsync(AsyncEventSequencer* sequencer) override { - trunks_service_.reset(new trunks::TrunksService( - bus_, - background_transceiver_.get())); - trunks_service_->Register( - sequencer->GetHandler("Register() failed.", true)); - } - - - private: - std::unique_ptr<trunks::TrunksService> trunks_service_; - std::unique_ptr<trunks::CommandTransceiver> transceiver_; - // Thread for executing TPM comands. - std::unique_ptr<base::Thread> background_thread_; - std::unique_ptr<trunks::TrunksFactory> factory_; - std::unique_ptr<trunks::ResourceManager> resource_manager_; - std::unique_ptr<trunks::CommandTransceiver> background_transceiver_; - - DISALLOW_COPY_AND_ASSIGN(TrunksDaemon); -}; - int main(int argc, char **argv) { base::CommandLine::Init(argc, argv); base::CommandLine *cl = base::CommandLine::ForCurrentProcess(); @@ -118,17 +79,45 @@ int main(int argc, char **argv) { flags |= brillo::kLogToStderr; } brillo::InitLog(flags); - trunks::CommandTransceiver *transceiver; + + // Create a service instance before anything else so objects like + // AtExitManager exist. +#if defined(USE_BINDER_IPC) + trunks::TrunksBinderService service; +#else + trunks::TrunksDBusService service; +#endif + + // Chain together command transceivers: + // [IPC] --> BackgroundCommandTransceiver + // --> ResourceManager + // --> TpmHandle + // --> [TPM] + trunks::CommandTransceiver *low_level_transceiver; if (cl->HasSwitch("ftdi")) { - transceiver = new trunks::TrunksFtdiSpi(); + LOG(INFO) << "Sending commands to FTDI SPI."; + low_level_transceiver = new trunks::TrunksFtdiSpi(); } else if (cl->HasSwitch("simulator")) { - transceiver = new trunks::TpmSimulatorHandle(); + LOG(INFO) << "Sending commands to simulator."; + low_level_transceiver = new trunks::TpmSimulatorHandle(); } else { - transceiver = new trunks::TpmHandle(); + low_level_transceiver = new trunks::TpmHandle(); } - CHECK(transceiver->Init()) << "Error initializing transceiver"; - TrunksDaemon daemon(transceiver); + CHECK(low_level_transceiver->Init()) + << "Error initializing TPM communication."; + // This needs to be *after* opening the TPM handle and *before* starting the + // background thread. InitMinijailSandbox(); - LOG(INFO) << "Trunks Service Started"; - return daemon.Run(); + base::Thread background_thread(kBackgroundThreadName); + CHECK(background_thread.Start()) << "Failed to start background thread."; + trunks::TrunksFactoryImpl factory(low_level_transceiver); + trunks::ResourceManager resource_manager(factory, low_level_transceiver); + background_thread.task_runner()->PostNonNestableTask( + FROM_HERE, base::Bind(&trunks::ResourceManager::Initialize, + base::Unretained(&resource_manager))); + trunks::BackgroundCommandTransceiver background_transceiver( + &resource_manager, background_thread.task_runner()); + service.set_transceiver(&background_transceiver); + LOG(INFO) << "Trunks service started."; + return service.Run(); } diff --git a/trunks/trunksd.rc b/trunks/trunksd.rc new file mode 100644 index 0000000..f672515 --- /dev/null +++ b/trunks/trunksd.rc @@ -0,0 +1,8 @@ +on post-fs-data + mkdir /data/misc/trunksd 0700 system system + +service trunksd /system/bin/trunksd + class late_start + user root + group root + oneshot |