1 // 2 // Copyright (C) 2015 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 "tpm_manager/server/tpm_nvram_impl.h" 18 19 #include <arpa/inet.h> 20 21 #include <string> 22 23 #include <base/logging.h> 24 #include <base/stl_util.h> 25 #include <trousers/scoped_tss_type.h> 26 27 #include "tpm_manager/common/local_data.pb.h" 28 #include "tpm_manager/server/local_data_store.h" 29 #include "tpm_manager/server/tpm_util.h" 30 31 namespace { 32 33 // PCR0 at locality 1 is used to differentiate between developed and normal 34 // mode. Restricting nvram to the PCR0 value in locality 1 prevents nvram from 35 // persisting across mode switch. 36 const unsigned int kTpmBootPCR = 0; 37 const unsigned int kTpmPCRLocality = 1; 38 39 } // namespace 40 41 namespace tpm_manager { 42 43 using trousers::ScopedTssMemory; 44 using trousers::ScopedTssNvStore; 45 using trousers::ScopedTssPcrs; 46 47 TpmNvramImpl::TpmNvramImpl(LocalDataStore* local_data_store) 48 : local_data_store_(local_data_store) {} 49 50 bool TpmNvramImpl::DefineNvram(uint32_t index, size_t length) { 51 ScopedTssNvStore nv_handle(tpm_connection_.GetContext()); 52 if (!(InitializeNvramHandle(&nv_handle, index) && 53 SetOwnerPolicy(&nv_handle))) { 54 return false; 55 } 56 TSS_RESULT result; 57 result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_DATASIZE, 58 0, length); 59 if (TPM_ERROR(result)) { 60 TPM_LOG(ERROR, result) << "Could not set size on NVRAM object: " << length; 61 return false; 62 } 63 // Restrict to only one write. 64 result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_PERMISSIONS, 65 0, TPM_NV_PER_WRITEDEFINE); 66 if (TPM_ERROR(result)) { 67 TPM_LOG(ERROR, result) << "Could not set PER_WRITEDEFINE on NVRAM object"; 68 return false; 69 } 70 // Restrict to writing only with owner authorization. 71 result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_PERMISSIONS, 72 0, TPM_NV_PER_OWNERWRITE); 73 if (TPM_ERROR(result)) { 74 TPM_LOG(ERROR, result) << "Could not set PER_OWNERWRITE on NVRAM object"; 75 return false; 76 } 77 ScopedTssPcrs pcr_handle(tpm_connection_.GetContext()); 78 if (!SetCompositePcr0(&pcr_handle)) { 79 return false; 80 } 81 result = Tspi_NV_DefineSpace(nv_handle, 82 pcr_handle /* ReadPCRs restricted to PCR0 */, 83 pcr_handle /* WritePCRs restricted to PCR0 */); 84 if (TPM_ERROR(result)) { 85 TPM_LOG(ERROR, result) << "Could not define NVRAM space: " << index; 86 return false; 87 } 88 return true; 89 } 90 91 bool TpmNvramImpl::DestroyNvram(uint32_t index) { 92 bool defined; 93 if (!IsNvramDefined(index, &defined)) { 94 return false; 95 } 96 if (!defined) { 97 // If the nvram space is not defined, we don't need to destroy it. 98 return true; 99 } 100 ScopedTssNvStore nv_handle(tpm_connection_.GetContext()); 101 if (!(InitializeNvramHandle(&nv_handle, index) && 102 SetOwnerPolicy(&nv_handle))) { 103 return false; 104 } 105 TSS_RESULT result = Tspi_NV_ReleaseSpace(nv_handle); 106 if (TPM_ERROR(result)) { 107 TPM_LOG(ERROR, result) << "Could not release NVRAM space: " << index; 108 return false; 109 } 110 return true; 111 } 112 113 bool TpmNvramImpl::WriteNvram(uint32_t index, const std::string& data) { 114 ScopedTssNvStore nv_handle(tpm_connection_.GetContext()); 115 if (!(InitializeNvramHandle(&nv_handle, index) && 116 SetOwnerPolicy(&nv_handle))) { 117 return false; 118 } 119 TSS_RESULT result = Tspi_NV_WriteValue( 120 nv_handle, 0 /* offset */, data.size(), 121 reinterpret_cast<BYTE *>(const_cast<char*>(data.data()))); 122 if (TPM_ERROR(result)) { 123 TPM_LOG(ERROR, result) << "Could not write to NVRAM space: " << index; 124 return false; 125 } 126 return true; 127 } 128 129 bool TpmNvramImpl::ReadNvram(uint32_t index, std::string* data) { 130 CHECK(data); 131 TSS_RESULT result; 132 ScopedTssNvStore nv_handle(tpm_connection_.GetContext()); 133 if (!InitializeNvramHandle(&nv_handle, index)) { 134 return false; 135 } 136 size_t nvram_size; 137 if (!GetNvramSize(index, &nvram_size)) { 138 return false; 139 } 140 data->resize(nvram_size); 141 // The Tpm1.2 Specification defines the maximum read size of 128 bytes. 142 // Therefore we have to loop through the data returned. 143 const size_t kMaxDataSize = 128; 144 uint32_t offset = 0; 145 while (offset < nvram_size) { 146 uint32_t chunk_size = std::max(nvram_size - offset, kMaxDataSize); 147 ScopedTssMemory space_data(tpm_connection_.GetContext()); 148 if ((result = Tspi_NV_ReadValue(nv_handle, offset, &chunk_size, 149 space_data.ptr()))) { 150 TPM_LOG(ERROR, result) << "Could not read from NVRAM space: " << index; 151 return false; 152 } 153 if (!space_data.value()) { 154 LOG(ERROR) << "No data read from NVRAM space: " << index; 155 return false; 156 } 157 CHECK_LE((offset + chunk_size), data->size()); 158 data->replace(offset, 159 chunk_size, 160 reinterpret_cast<char*>(space_data.value()), 161 chunk_size); 162 offset += chunk_size; 163 } 164 return true; 165 } 166 167 bool TpmNvramImpl::IsNvramDefined(uint32_t index, bool* defined) { 168 CHECK(defined); 169 uint32_t nv_list_data_length = 0; 170 ScopedTssMemory nv_list_data(tpm_connection_.GetContext()); 171 TSS_RESULT result = Tspi_TPM_GetCapability(tpm_connection_.GetTpm(), 172 TSS_TPMCAP_NV_LIST, 173 0, 174 NULL, 175 &nv_list_data_length, 176 nv_list_data.ptr()); 177 if (TPM_ERROR(result)) { 178 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability"; 179 return false; 180 } 181 // Walk the list and check if the index exists. 182 uint32_t* nv_list = reinterpret_cast<uint32_t*>(nv_list_data.value()); 183 uint32_t nv_list_length = nv_list_data_length / sizeof(uint32_t); 184 index = htonl(index); // TPM data is network byte order. 185 for (uint32_t i = 0; i < nv_list_length; ++i) { 186 if (index == nv_list[i]) { 187 *defined = true; 188 return true; 189 } 190 } 191 *defined = false; 192 return true; 193 } 194 195 bool TpmNvramImpl::IsNvramLocked(uint32_t index, bool* locked) { 196 CHECK(locked); 197 uint32_t nv_index_data_length = 0; 198 ScopedTssMemory nv_index_data(tpm_connection_.GetContext()); 199 TSS_RESULT result = Tspi_TPM_GetCapability(tpm_connection_.GetTpm(), 200 TSS_TPMCAP_NV_INDEX, 201 sizeof(index), 202 reinterpret_cast<BYTE*>(&index), 203 &nv_index_data_length, 204 nv_index_data.ptr()); 205 if (TPM_ERROR(result)) { 206 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability"; 207 return false; 208 } 209 if (nv_index_data_length < (sizeof(uint32_t) + sizeof(TPM_BOOL))) { 210 return false; 211 } 212 // TPM_NV_DATA_PUBLIC->bWriteDefine is the second to last element in the 213 // struct. 214 uint32_t* nv_data_public = reinterpret_cast<uint32_t*>( 215 nv_index_data.value() + nv_index_data_length - 216 (sizeof(uint32_t) + sizeof(TPM_BOOL))); 217 *locked = (*nv_data_public != 0); 218 return true; 219 } 220 221 bool TpmNvramImpl::GetNvramSize(uint32_t index, size_t* size) { 222 CHECK(size); 223 UINT32 nv_index_data_length = 0; 224 ScopedTssMemory nv_index_data(tpm_connection_.GetContext()); 225 TSS_RESULT result = Tspi_TPM_GetCapability(tpm_connection_.GetTpm(), 226 TSS_TPMCAP_NV_INDEX, 227 sizeof(index), 228 reinterpret_cast<BYTE*>(&index), 229 &nv_index_data_length, 230 nv_index_data.ptr()); 231 if (TPM_ERROR(result)) { 232 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability"; 233 return false; 234 } 235 if (nv_index_data_length < sizeof(uint32_t)) { 236 return false; 237 } 238 // TPM_NV_DATA_PUBLIC->dataSize is the last element in the struct. 239 uint32_t* nv_data_public = reinterpret_cast<uint32_t*>( 240 nv_index_data.value() + nv_index_data_length - 241 sizeof(uint32_t)); 242 *size = htonl(*nv_data_public); 243 return true; 244 } 245 246 bool TpmNvramImpl::InitializeNvramHandle(ScopedTssNvStore* nv_handle, 247 uint32_t index) { 248 249 TSS_RESULT result = Tspi_Context_CreateObject(tpm_connection_.GetContext(), 250 TSS_OBJECT_TYPE_NV, 251 0, 252 nv_handle->ptr()); 253 if (TPM_ERROR(result)) { 254 TPM_LOG(ERROR, result) << "Could not acquire an NVRAM object handle"; 255 return false; 256 } 257 result = Tspi_SetAttribUint32( 258 nv_handle->value(), TSS_TSPATTRIB_NV_INDEX, 0, index); 259 if (TPM_ERROR(result)) { 260 TPM_LOG(ERROR, result) << "Could not set index on NVRAM object: " << index; 261 return false; 262 } 263 return true; 264 } 265 266 bool TpmNvramImpl::SetOwnerPolicy(ScopedTssNvStore* nv_handle) { 267 trousers::ScopedTssPolicy policy_handle(tpm_connection_.GetContext()); 268 TSS_RESULT result; 269 result = Tspi_Context_CreateObject(tpm_connection_.GetContext(), 270 TSS_OBJECT_TYPE_POLICY, 271 TSS_POLICY_USAGE, 272 policy_handle.ptr()); 273 if (TPM_ERROR(result)) { 274 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject"; 275 return false; 276 } 277 std::string owner_password; 278 if (!GetOwnerPassword(&owner_password)) { 279 return false; 280 } 281 result = Tspi_Policy_SetSecret( 282 policy_handle, 283 TSS_SECRET_MODE_PLAIN, 284 owner_password.size(), 285 reinterpret_cast<BYTE *>(const_cast<char*>(owner_password.data()))); 286 if (TPM_ERROR(result)) { 287 TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret"; 288 return false; 289 } 290 result = Tspi_Policy_AssignToObject(policy_handle.value(), 291 nv_handle->value()); 292 if (TPM_ERROR(result)) { 293 TPM_LOG(ERROR, result) << "Could not set NVRAM object policy."; 294 return false; 295 } 296 return true; 297 } 298 299 bool TpmNvramImpl::SetCompositePcr0(ScopedTssPcrs* pcr_handle) { 300 TSS_RESULT result = Tspi_Context_CreateObject(tpm_connection_.GetContext(), 301 TSS_OBJECT_TYPE_PCRS, 302 TSS_PCRS_STRUCT_INFO_SHORT, 303 pcr_handle->ptr()); 304 if (TPM_ERROR(result)) { 305 TPM_LOG(ERROR, result) << "Could not acquire PCR object handle"; 306 return false; 307 } 308 uint32_t pcr_len; 309 std::string owner_password; 310 if (!GetOwnerPassword(&owner_password)) { 311 return false; 312 } 313 ScopedTssMemory pcr_value(tpm_connection_.GetContext()); 314 result = Tspi_TPM_PcrRead(tpm_connection_.GetTpmWithAuth(owner_password), 315 kTpmBootPCR, 316 &pcr_len, 317 pcr_value.ptr()); 318 if (TPM_ERROR(result)) { 319 TPM_LOG(ERROR, result) << "Could not read PCR0 value"; 320 return false; 321 } 322 result = Tspi_PcrComposite_SetPcrValue(pcr_handle->value(), 323 kTpmBootPCR, 324 pcr_len, 325 pcr_value.value()); 326 if (TPM_ERROR(result)) { 327 TPM_LOG(ERROR, result) << "Could not set value for PCR0 in PCR handle"; 328 return false; 329 } 330 result = Tspi_PcrComposite_SetPcrLocality(pcr_handle->value(), 331 kTpmPCRLocality); 332 if (TPM_ERROR(result)) { 333 TPM_LOG(ERROR, result) << "Could not set locality for PCR0 in PCR handle"; 334 return false; 335 } 336 return true; 337 } 338 339 bool TpmNvramImpl::GetOwnerPassword(std::string* owner_password) { 340 LocalData local_data; 341 if (!local_data_store_->Read(&local_data)) { 342 LOG(ERROR) << "Error reading local data for owner password."; 343 return false; 344 } 345 if (local_data.owner_password().empty()) { 346 LOG(ERROR) << "No owner password present in tpm local_data."; 347 return false; 348 } 349 owner_password->assign(local_data.owner_password()); 350 return true; 351 } 352 353 } // namespace tpm_manager 354