1259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi//
2259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi// Copyright (C) 2015 The Android Open Source Project
3259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi//
4259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi// Licensed under the Apache License, Version 2.0 (the "License");
5259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi// you may not use this file except in compliance with the License.
6259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi// You may obtain a copy of the License at
7259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi//
8259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi//      http://www.apache.org/licenses/LICENSE-2.0
9259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi//
10259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi// Unless required by applicable law or agreed to in writing, software
11259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi// distributed under the License is distributed on an "AS IS" BASIS,
12259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi// See the License for the specific language governing permissions and
14259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi// limitations under the License.
15259fa1be39c0a35ec374fe127ba49d1c5ed5eb18Utkarsh Sanghi//
16565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi
17565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi#include "tpm_manager/server/tpm_connection.h"
18565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi
19565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi#include <base/logging.h>
2050e52ff6bcc478118a1cdec27903a5af5061d77bUtkarsh Sanghi#include <base/stl_util.h>
21565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi#include <base/threading/platform_thread.h>
22565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi#include <base/time/time.h>
23565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi#include <trousers/tss.h>
24565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi#include <trousers/trousers.h>  // NOLINT(build/include_alpha)
25565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi
2650e52ff6bcc478118a1cdec27903a5af5061d77bUtkarsh Sanghi#include "tpm_manager/server/tpm_util.h"
2750e52ff6bcc478118a1cdec27903a5af5061d77bUtkarsh Sanghi
28565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghinamespace {
29565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi
30565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghiconst int kTpmConnectRetries = 10;
31565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghiconst int kTpmConnectIntervalMs = 100;
32565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi
33565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi}  // namespace
34565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi
35565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghinamespace tpm_manager {
36565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi
37a94133441da308b30c6fe18cc4e2b866498ee401Darren KrahnTpmConnection::TpmConnection(const std::string& authorization_value)
38a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    : authorization_value_(authorization_value) {}
39a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn
4050e52ff6bcc478118a1cdec27903a5af5061d77bUtkarsh SanghiTSS_HCONTEXT TpmConnection::GetContext() {
4150e52ff6bcc478118a1cdec27903a5af5061d77bUtkarsh Sanghi  if (!ConnectContextIfNeeded()) {
4250e52ff6bcc478118a1cdec27903a5af5061d77bUtkarsh Sanghi    return 0;
4350e52ff6bcc478118a1cdec27903a5af5061d77bUtkarsh Sanghi  }
4450e52ff6bcc478118a1cdec27903a5af5061d77bUtkarsh Sanghi  return context_.value();
4550e52ff6bcc478118a1cdec27903a5af5061d77bUtkarsh Sanghi}
46565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi
47565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh SanghiTSS_HTPM TpmConnection::GetTpm() {
48565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  if (!ConnectContextIfNeeded()) {
49565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi    return 0;
50565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  }
51565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  TSS_RESULT result;
52565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  TSS_HTPM tpm_handle;
534dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  if (TPM_ERROR(result =
544dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                    Tspi_Context_GetTpmObject(context_.value(), &tpm_handle))) {
55565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi    TPM_LOG(ERROR, result) << "Error getting a handle to the TPM.";
56565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi    return 0;
57565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  }
58565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  return tpm_handle;
59565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi}
60565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi
61565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghibool TpmConnection::ConnectContextIfNeeded() {
62565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  if (context_.value() != 0) {
63565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi    return true;
64565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  }
65565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  TSS_RESULT result;
66565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  if (TPM_ERROR(result = Tspi_Context_Create(context_.ptr()))) {
67565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi    TPM_LOG(ERROR, result) << "Error connecting to TPM.";
68565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi    return false;
69565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  }
70565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  // We retry on failure. It might be that tcsd is starting up.
71565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  for (int i = 0; i < kTpmConnectRetries; i++) {
72565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi    if (TPM_ERROR(result = Tspi_Context_Connect(context_, nullptr))) {
73565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi      if (ERROR_CODE(result) == TSS_E_COMM_FAILURE) {
74565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi        base::PlatformThread::Sleep(
75565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi            base::TimeDelta::FromMilliseconds(kTpmConnectIntervalMs));
76565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi      } else {
77565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi        TPM_LOG(ERROR, result) << "Error connecting to TPM.";
78565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi        return false;
79565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi      }
80565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi    } else {
81565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi      break;
82565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi    }
83565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi  }
84a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  if (context_.value() == 0) {
85a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    LOG(ERROR) << "Unexpected NULL context.";
86a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    return false;
87a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  }
88a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  // If we don't need to set an authorization value, we're done.
89a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  if (authorization_value_.empty()) {
90a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    return true;
91a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  }
92a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn
93a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  TSS_HTPM tpm_handle;
94a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  if (TPM_ERROR(result =
95a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn                    Tspi_Context_GetTpmObject(context_.value(), &tpm_handle))) {
96a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    TPM_LOG(ERROR, result) << "Error getting a handle to the TPM.";
97a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    context_.reset();
98a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    return false;
99a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  }
100a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  TSS_HPOLICY tpm_usage_policy;
101a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  if (TPM_ERROR(result = Tspi_GetPolicyObject(tpm_handle, TSS_POLICY_USAGE,
102a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn                                              &tpm_usage_policy))) {
103a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    TPM_LOG(ERROR, result) << "Error calling Tspi_GetPolicyObject";
104a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    context_.reset();
105a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    return false;
106a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  }
107a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  if (TPM_ERROR(result = Tspi_Policy_SetSecret(
108a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn                    tpm_usage_policy, TSS_SECRET_MODE_PLAIN,
109a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn                    authorization_value_.size(),
110a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn                    reinterpret_cast<BYTE*>(
111a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn                        const_cast<char*>(authorization_value_.data()))))) {
112a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
113a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    context_.reset();
114a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn    return false;
115a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  }
116a94133441da308b30c6fe18cc4e2b866498ee401Darren Krahn  return true;
117565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi}
118565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi
119565f88fe8ebdabefe07e5d5cb65ae9bcab509368Utkarsh Sanghi}  // namespace tpm_manager
120