Home | History | Annotate | Download | only in trunks
      1 //
      2 // Copyright (C) 2014 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "trunks/tpm_handle.h"
     18 
     19 #include <fcntl.h>
     20 #include <unistd.h>
     21 
     22 #include <base/callback.h>
     23 #include <base/logging.h>
     24 #include <base/posix/eintr_wrapper.h>
     25 
     26 namespace {
     27 
     28 const char kTpmDevice[] = "/dev/tpm0";
     29 const uint32_t kTpmBufferSize = 4096;
     30 const int kInvalidFileDescriptor = -1;
     31 
     32 }  // namespace
     33 
     34 namespace trunks {
     35 
     36 TpmHandle::TpmHandle() : fd_(kInvalidFileDescriptor) {}
     37 
     38 TpmHandle::~TpmHandle() {
     39   int result = IGNORE_EINTR(close(fd_));
     40   if (result == -1) {
     41     PLOG(ERROR) << "TPM: couldn't close " << kTpmDevice;
     42   }
     43   LOG(INFO) << "TPM: " << kTpmDevice << " closed successfully";
     44 }
     45 
     46 bool TpmHandle::Init() {
     47   if (fd_ != kInvalidFileDescriptor) {
     48     VLOG(1) << "Tpm already initialized.";
     49     return true;
     50   }
     51   fd_ = HANDLE_EINTR(open(kTpmDevice, O_RDWR));
     52   if (fd_ == kInvalidFileDescriptor) {
     53     PLOG(ERROR) << "TPM: Error opening tpm0 file descriptor at " << kTpmDevice;
     54     return false;
     55   }
     56   LOG(INFO) << "TPM: " << kTpmDevice << " opened successfully";
     57   return true;
     58 }
     59 
     60 void TpmHandle::SendCommand(const std::string& command,
     61                             const ResponseCallback& callback) {
     62   callback.Run(SendCommandAndWait(command));
     63 }
     64 
     65 std::string TpmHandle::SendCommandAndWait(const std::string& command) {
     66   std::string response;
     67   TPM_RC result = SendCommandInternal(command, &response);
     68   if (result != TPM_RC_SUCCESS) {
     69     response = CreateErrorResponse(result);
     70   }
     71   return response;
     72 }
     73 
     74 TPM_RC TpmHandle::SendCommandInternal(const std::string& command,
     75                                       std::string* response) {
     76   CHECK_NE(fd_, kInvalidFileDescriptor);
     77   int result = HANDLE_EINTR(write(fd_, command.data(), command.length()));
     78   if (result < 0) {
     79     PLOG(ERROR) << "TPM: Error writing to TPM handle.";
     80     return TRUNKS_RC_WRITE_ERROR;
     81   }
     82   if (static_cast<size_t>(result) != command.length()) {
     83     LOG(ERROR) << "TPM: Error writing to TPM handle: " << result << " vs "
     84                << command.length();
     85     return TRUNKS_RC_WRITE_ERROR;
     86   }
     87   char response_buf[kTpmBufferSize];
     88   result = HANDLE_EINTR(read(fd_, response_buf, kTpmBufferSize));
     89   if (result < 0) {
     90     PLOG(ERROR) << "TPM: Error reading from TPM handle.";
     91     return TRUNKS_RC_READ_ERROR;
     92   }
     93   response->assign(response_buf, static_cast<size_t>(result));
     94   return TPM_RC_SUCCESS;
     95 }
     96 
     97 }  // namespace trunks
     98