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