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/tpm_manager.pb.h"
28#include "tpm_manager/server/local_data_store.h"
29#include "tpm_manager/server/tpm_util.h"
30
31namespace tpm_manager {
32
33using trousers::ScopedTssMemory;
34using trousers::ScopedTssNvStore;
35using trousers::ScopedTssPcrs;
36
37namespace {
38
39// PCR0 at locality 1 is used to differentiate between developed and normal
40// mode. Restricting nvram to the PCR0 value in locality 1 prevents nvram from
41// persisting across mode switch.
42const unsigned int kTpmBootPCR = 0;
43const unsigned int kTpmPCRLocality = 1;
44
45void MapAttributesFromTpm(TPM_NV_PER_ATTRIBUTES tpm_flags,
46                          std::vector<NvramSpaceAttribute>* attributes) {
47  if (tpm_flags & TPM_NV_PER_WRITEDEFINE)
48    attributes->push_back(NVRAM_PERSISTENT_WRITE_LOCK);
49  if (tpm_flags & TPM_NV_PER_WRITE_STCLEAR)
50    attributes->push_back(NVRAM_BOOT_WRITE_LOCK);
51  if (tpm_flags & TPM_NV_PER_READ_STCLEAR)
52    attributes->push_back(NVRAM_BOOT_READ_LOCK);
53  if (tpm_flags & TPM_NV_PER_AUTHWRITE)
54    attributes->push_back(NVRAM_WRITE_AUTHORIZATION);
55  if (tpm_flags & TPM_NV_PER_AUTHREAD)
56    attributes->push_back(NVRAM_READ_AUTHORIZATION);
57  if (tpm_flags & TPM_NV_PER_GLOBALLOCK)
58    attributes->push_back(NVRAM_GLOBAL_LOCK);
59  if (tpm_flags & TPM_NV_PER_PPWRITE)
60    attributes->push_back(NVRAM_PLATFORM_WRITE);
61  if (tpm_flags & TPM_NV_PER_OWNERWRITE)
62    attributes->push_back(NVRAM_OWNER_WRITE);
63  if (tpm_flags & TPM_NV_PER_OWNERREAD)
64    attributes->push_back(NVRAM_OWNER_READ);
65}
66
67TPM_NV_PER_ATTRIBUTES MapAttributesToTpm(
68    const std::vector<NvramSpaceAttribute>& attributes) {
69  TPM_NV_PER_ATTRIBUTES tpm_flags = 0;
70  for (auto attribute : attributes) {
71    switch (attribute) {
72      case NVRAM_PERSISTENT_WRITE_LOCK:
73        tpm_flags |= TPM_NV_PER_WRITEDEFINE;
74        break;
75      case NVRAM_BOOT_WRITE_LOCK:
76        tpm_flags |= TPM_NV_PER_WRITE_STCLEAR;
77        break;
78      case NVRAM_BOOT_READ_LOCK:
79        tpm_flags |= TPM_NV_PER_READ_STCLEAR;
80        break;
81      case NVRAM_WRITE_AUTHORIZATION:
82        tpm_flags |= TPM_NV_PER_AUTHWRITE;
83        break;
84      case NVRAM_READ_AUTHORIZATION:
85        tpm_flags |= TPM_NV_PER_AUTHREAD;
86        break;
87      case NVRAM_GLOBAL_LOCK:
88        tpm_flags |= TPM_NV_PER_GLOBALLOCK;
89        break;
90      case NVRAM_PLATFORM_WRITE:
91        tpm_flags |= TPM_NV_PER_PPWRITE;
92        break;
93      case NVRAM_OWNER_WRITE:
94        tpm_flags |= TPM_NV_PER_OWNERWRITE;
95        break;
96      case NVRAM_OWNER_READ:
97        tpm_flags |= TPM_NV_PER_OWNERREAD;
98        break;
99      default:
100        break;
101    }
102  }
103  return tpm_flags;
104}
105
106NvramResult MapTpmError(TSS_RESULT tpm_error) {
107  switch (TPM_ERROR(tpm_error)) {
108    case TPM_SUCCESS:
109      return NVRAM_RESULT_SUCCESS;
110    case TPM_E_BAD_PARAMETER:
111    case TPM_E_PER_NOWRITE:
112    case TPM_E_AUTH_CONFLICT:
113      return NVRAM_RESULT_INVALID_PARAMETER;
114    case TPM_E_AREA_LOCKED:
115    case TPM_E_READ_ONLY:
116    case TPM_E_WRITE_LOCKED:
117    case TPM_E_DISABLED_CMD:
118      return NVRAM_RESULT_OPERATION_DISABLED;
119    case TPM_E_AUTHFAIL:
120    case TPM_E_NO_NV_PERMISSION:
121    case TPM_E_WRONGPCRVAL:
122      return NVRAM_RESULT_ACCESS_DENIED;
123    case TPM_E_NOSPACE:
124    case TPM_E_RESOURCES:
125    case TPM_E_SIZE:
126      return NVRAM_RESULT_INSUFFICIENT_SPACE;
127    case TPM_E_BADINDEX:
128    case TPM_E_BAD_HANDLE:
129      return NVRAM_RESULT_SPACE_DOES_NOT_EXIST;
130  }
131  return NVRAM_RESULT_DEVICE_ERROR;
132}
133
134}  // namespace
135
136TpmNvramImpl::TpmNvramImpl(LocalDataStore* local_data_store)
137    : local_data_store_(local_data_store) {}
138
139NvramResult TpmNvramImpl::DefineSpace(
140    uint32_t index,
141    size_t size,
142    const std::vector<NvramSpaceAttribute>& attributes,
143    const std::string& authorization_value,
144    NvramSpacePolicy policy) {
145  std::string owner_password;
146  if (!GetOwnerPassword(&owner_password)) {
147    return NVRAM_RESULT_OPERATION_DISABLED;
148  }
149  TpmConnection owner_connection(owner_password);
150  ScopedTssNvStore nv_handle(owner_connection.GetContext());
151  if (!InitializeNvramHandle(index, &nv_handle, &owner_connection)) {
152    return NVRAM_RESULT_DEVICE_ERROR;
153  }
154  TSS_RESULT result;
155  result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_DATASIZE, 0, size);
156  if (TPM_ERROR(result)) {
157    TPM_LOG(ERROR, result) << "Could not set size on NVRAM object: " << size;
158    return NVRAM_RESULT_DEVICE_ERROR;
159  }
160  // Set permissions attributes.
161  result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_PERMISSIONS, 0,
162                                MapAttributesToTpm(attributes));
163  if (TPM_ERROR(result)) {
164    TPM_LOG(ERROR, result) << "Could not set permissions on NVRAM object";
165    return NVRAM_RESULT_DEVICE_ERROR;
166  }
167  // Set authorization.
168  if (!authorization_value.empty() &&
169      !SetUsagePolicy(authorization_value, &nv_handle, &owner_connection)) {
170    return NVRAM_RESULT_DEVICE_ERROR;
171  }
172  // Bind to PCR0.
173  TSS_HPCRS pcr_handle = 0;
174  ScopedTssPcrs scoped_pcr_handle(owner_connection.GetContext());
175  if (policy == NVRAM_POLICY_PCR0) {
176    if (!SetCompositePcr0(&scoped_pcr_handle, &owner_connection)) {
177      return NVRAM_RESULT_DEVICE_ERROR;
178    }
179    pcr_handle = scoped_pcr_handle;
180  }
181  result = Tspi_NV_DefineSpace(nv_handle, pcr_handle, /*Read*/
182                               pcr_handle /*Write*/);
183  if (TPM_ERROR(result)) {
184    TPM_LOG(ERROR, result) << "Could not define NVRAM space: " << index;
185    return MapTpmError(result);
186  }
187  return NVRAM_RESULT_SUCCESS;
188}
189
190NvramResult TpmNvramImpl::DestroySpace(uint32_t index) {
191  std::string owner_password;
192  if (!GetOwnerPassword(&owner_password)) {
193    return NVRAM_RESULT_OPERATION_DISABLED;
194  }
195  TpmConnection owner_connection(owner_password);
196  ScopedTssNvStore nv_handle(owner_connection.GetContext());
197  if (!InitializeNvramHandle(index, &nv_handle, &owner_connection)) {
198    return NVRAM_RESULT_DEVICE_ERROR;
199  }
200  TSS_RESULT result = Tspi_NV_ReleaseSpace(nv_handle);
201  if (TPM_ERROR(result)) {
202    TPM_LOG(ERROR, result) << "Could not release NVRAM space: " << index;
203    return MapTpmError(result);
204  }
205  return NVRAM_RESULT_SUCCESS;
206}
207
208NvramResult TpmNvramImpl::WriteSpace(uint32_t index,
209                                     const std::string& data,
210                                     const std::string& authorization_value) {
211  std::vector<NvramSpaceAttribute> attributes;
212  NvramResult result =
213      GetSpaceInfo(index, nullptr, nullptr, nullptr, &attributes, nullptr);
214  if (result != NVRAM_RESULT_SUCCESS) {
215    return result;
216  }
217  ScopedTssNvStore nv_handle(tpm_connection_.GetContext());
218  if (!InitializeNvramHandle(index, &nv_handle, &tpm_connection_)) {
219    return NVRAM_RESULT_DEVICE_ERROR;
220  }
221  for (const auto& attribute : attributes) {
222    if (attribute == NVRAM_OWNER_WRITE) {
223      if (!SetOwnerPolicy(&nv_handle)) {
224        return NVRAM_RESULT_OPERATION_DISABLED;
225      }
226      break;
227    }
228    if (attribute == NVRAM_WRITE_AUTHORIZATION) {
229      if (!SetUsagePolicy(authorization_value, &nv_handle, &tpm_connection_)) {
230        return NVRAM_RESULT_DEVICE_ERROR;
231      }
232      break;
233    }
234  }
235  TSS_RESULT tpm_result = Tspi_NV_WriteValue(
236      nv_handle, 0 /* offset */, data.size(),
237      reinterpret_cast<BYTE*>(const_cast<char*>(data.data())));
238  if (TPM_ERROR(tpm_result)) {
239    TPM_LOG(ERROR, tpm_result) << "Could not write to NVRAM space: " << index;
240    return MapTpmError(tpm_result);
241  }
242  return NVRAM_RESULT_SUCCESS;
243}
244
245NvramResult TpmNvramImpl::ReadSpace(uint32_t index,
246                                    std::string* data,
247                                    const std::string& authorization_value) {
248  CHECK(data);
249  size_t nvram_size;
250  std::vector<NvramSpaceAttribute> attributes;
251  NvramResult result =
252      GetSpaceInfo(index, &nvram_size, nullptr, nullptr, &attributes, nullptr);
253  if (result != NVRAM_RESULT_SUCCESS) {
254    return result;
255  }
256  ScopedTssNvStore nv_handle(tpm_connection_.GetContext());
257  if (!InitializeNvramHandle(index, &nv_handle, &tpm_connection_)) {
258    return NVRAM_RESULT_DEVICE_ERROR;
259  }
260  for (const auto& attribute : attributes) {
261    if (attribute == NVRAM_OWNER_READ) {
262      if (!SetOwnerPolicy(&nv_handle)) {
263        return NVRAM_RESULT_OPERATION_DISABLED;
264      }
265      break;
266    }
267    if (attribute == NVRAM_READ_AUTHORIZATION) {
268      if (!SetUsagePolicy(authorization_value, &nv_handle, &tpm_connection_)) {
269        return NVRAM_RESULT_DEVICE_ERROR;
270      }
271      break;
272    }
273  }
274  data->resize(nvram_size);
275  // The Tpm1.2 Specification defines the maximum read size of 128 bytes.
276  // Therefore we have to loop through the data returned.
277  const size_t kMaxDataSize = 128;
278  uint32_t offset = 0;
279  while (offset < nvram_size) {
280    uint32_t chunk_size = std::min(nvram_size - offset, kMaxDataSize);
281    ScopedTssMemory space_data(tpm_connection_.GetContext());
282    TSS_RESULT tpm_result =
283        Tspi_NV_ReadValue(nv_handle, offset, &chunk_size, space_data.ptr());
284    if (TPM_ERROR(tpm_result)) {
285      TPM_LOG(ERROR, tpm_result) << "Could not read from NVRAM space: "
286                                 << index;
287      data->clear();
288      return MapTpmError(tpm_result);
289    }
290    if (!space_data.value()) {
291      LOG(ERROR) << "No data read from NVRAM space: " << index;
292      data->clear();
293      return NVRAM_RESULT_DEVICE_ERROR;
294    }
295    CHECK_LE((offset + chunk_size), data->size());
296    data->replace(offset, chunk_size,
297                  reinterpret_cast<char*>(space_data.value()), chunk_size);
298    offset += chunk_size;
299  }
300  return NVRAM_RESULT_SUCCESS;
301}
302
303NvramResult TpmNvramImpl::LockSpace(uint32_t index,
304                                    bool lock_read,
305                                    bool lock_write,
306                                    const std::string& authorization_value) {
307  std::vector<NvramSpaceAttribute> attributes;
308  NvramResult result =
309      GetSpaceInfo(index, nullptr, nullptr, nullptr, &attributes, nullptr);
310  if (result != NVRAM_RESULT_SUCCESS) {
311    return result;
312  }
313  if (lock_read) {
314    ScopedTssNvStore nv_handle(tpm_connection_.GetContext());
315    if (!InitializeNvramHandle(index, &nv_handle, &tpm_connection_)) {
316      return NVRAM_RESULT_DEVICE_ERROR;
317    }
318    for (const auto& attribute : attributes) {
319      if (attribute == NVRAM_OWNER_READ) {
320        if (!SetOwnerPolicy(&nv_handle)) {
321          return NVRAM_RESULT_OPERATION_DISABLED;
322        }
323        break;
324      }
325      if (attribute == NVRAM_READ_AUTHORIZATION) {
326        if (!SetUsagePolicy(authorization_value, &nv_handle,
327                            &tpm_connection_)) {
328          return NVRAM_RESULT_DEVICE_ERROR;
329        }
330        break;
331      }
332    }
333    uint32_t size = 0;
334    ScopedTssMemory space_data(tpm_connection_.GetContext());
335    TSS_RESULT tpm_result =
336        Tspi_NV_ReadValue(nv_handle, 0, &size, space_data.ptr());
337    if (TPM_ERROR(tpm_result)) {
338      TPM_LOG(ERROR, tpm_result) << "Could not lock read for NVRAM space: "
339                                 << index;
340      return MapTpmError(tpm_result);
341    }
342  }
343  if (lock_write) {
344    ScopedTssNvStore nv_handle(tpm_connection_.GetContext());
345    if (!InitializeNvramHandle(index, &nv_handle, &tpm_connection_)) {
346      return NVRAM_RESULT_DEVICE_ERROR;
347    }
348    for (const auto& attribute : attributes) {
349      if (attribute == NVRAM_OWNER_WRITE) {
350        if (!SetOwnerPolicy(&nv_handle)) {
351          return NVRAM_RESULT_OPERATION_DISABLED;
352        }
353        break;
354      }
355      if (attribute == NVRAM_WRITE_AUTHORIZATION) {
356        if (!SetUsagePolicy(authorization_value, &nv_handle,
357                            &tpm_connection_)) {
358          return NVRAM_RESULT_DEVICE_ERROR;
359        }
360        break;
361      }
362    }
363    BYTE not_used;
364    TSS_RESULT tpm_result = Tspi_NV_WriteValue(nv_handle, 0, 0, &not_used);
365    if (TPM_ERROR(tpm_result)) {
366      TPM_LOG(ERROR, tpm_result) << "Could not lock write for NVRAM space: "
367                                 << index;
368      return MapTpmError(tpm_result);
369    }
370  }
371  return NVRAM_RESULT_SUCCESS;
372}
373
374NvramResult TpmNvramImpl::ListSpaces(std::vector<uint32_t>* index_list) {
375  uint32_t nv_list_data_length = 0;
376  ScopedTssMemory nv_list_data(tpm_connection_.GetContext());
377  TSS_RESULT result =
378      Tspi_TPM_GetCapability(tpm_connection_.GetTpm(), TSS_TPMCAP_NV_LIST, 0,
379                             nullptr, &nv_list_data_length, nv_list_data.ptr());
380  if (TPM_ERROR(result)) {
381    TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
382    return MapTpmError(result);
383  }
384  // Walk the list and check if the index exists.
385  uint32_t* nv_list = reinterpret_cast<uint32_t*>(nv_list_data.value());
386  uint32_t nv_list_length = nv_list_data_length / sizeof(uint32_t);
387  for (uint32_t i = 0; i < nv_list_length; ++i) {
388    // TPM data is network byte order.
389    index_list->push_back(ntohl(nv_list[i]));
390  }
391  return NVRAM_RESULT_SUCCESS;
392}
393
394NvramResult TpmNvramImpl::GetSpaceInfo(
395    uint32_t index,
396    size_t* size,
397    bool* is_read_locked,
398    bool* is_write_locked,
399    std::vector<NvramSpaceAttribute>* attributes,
400    NvramSpacePolicy* policy) {
401  UINT32 nv_index_data_length = 0;
402  ScopedTssMemory nv_index_data(tpm_connection_.GetContext());
403  TSS_RESULT result =
404      Tspi_TPM_GetCapability(tpm_connection_.GetTpm(), TSS_TPMCAP_NV_INDEX,
405                             sizeof(index), reinterpret_cast<BYTE*>(&index),
406                             &nv_index_data_length, nv_index_data.ptr());
407  if (TPM_ERROR(result)) {
408    TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
409    return MapTpmError(result);
410  }
411  UINT64 offset = 0;
412  Trspi_UnloadBlob_NV_DATA_PUBLIC(&offset, nv_index_data.value(), nullptr);
413  if (nv_index_data_length < offset) {
414    LOG(ERROR) << "Not enough data from Tspi_TPM_GetCapability.";
415    return NVRAM_RESULT_DEVICE_ERROR;
416  }
417  TPM_NV_DATA_PUBLIC info;
418  offset = 0;
419  result =
420      Trspi_UnloadBlob_NV_DATA_PUBLIC(&offset, nv_index_data.value(), &info);
421  if (TPM_ERROR(result)) {
422    TPM_LOG(ERROR, result) << "Error calling Trspi_UnloadBlob_NV_DATA_PUBLIC";
423    return NVRAM_RESULT_DEVICE_ERROR;
424  }
425  if (size) {
426    *size = info.dataSize;
427  }
428  if (is_read_locked) {
429    *is_read_locked = info.bReadSTClear;
430  }
431  if (is_write_locked) {
432    *is_write_locked = info.bWriteSTClear || info.bWriteDefine;
433  }
434  if (attributes) {
435    MapAttributesFromTpm(info.permission.attributes, attributes);
436  }
437  if (policy) {
438    if (info.pcrInfoWrite.pcrSelection.sizeOfSelect > 0 &&
439        (info.pcrInfoWrite.pcrSelection.pcrSelect[0] & 1) != 0) {
440      *policy = NVRAM_POLICY_PCR0;
441    } else {
442      *policy = NVRAM_POLICY_NONE;
443    }
444  }
445  return NVRAM_RESULT_SUCCESS;
446}
447
448bool TpmNvramImpl::InitializeNvramHandle(uint32_t index,
449                                         ScopedTssNvStore* nv_handle,
450                                         TpmConnection* connection) {
451  TSS_RESULT result = Tspi_Context_CreateObject(
452      connection->GetContext(), TSS_OBJECT_TYPE_NV, 0, nv_handle->ptr());
453  if (TPM_ERROR(result)) {
454    TPM_LOG(ERROR, result) << "Could not acquire an NVRAM object handle";
455    return false;
456  }
457  result = Tspi_SetAttribUint32(nv_handle->value(), TSS_TSPATTRIB_NV_INDEX, 0,
458                                index);
459  if (TPM_ERROR(result)) {
460    TPM_LOG(ERROR, result) << "Could not set index on NVRAM object: " << index;
461    return false;
462  }
463  return true;
464}
465
466bool TpmNvramImpl::SetOwnerPolicy(ScopedTssNvStore* nv_handle) {
467  std::string owner_password;
468  if (!GetOwnerPassword(&owner_password)) {
469    return false;
470  }
471  return SetUsagePolicy(owner_password, nv_handle, &tpm_connection_);
472}
473
474bool TpmNvramImpl::SetUsagePolicy(const std::string& authorization_value,
475                                  trousers::ScopedTssNvStore* nv_handle,
476                                  TpmConnection* connection) {
477  trousers::ScopedTssPolicy policy_handle(connection->GetContext());
478  TSS_RESULT result;
479  result = Tspi_Context_CreateObject(connection->GetContext(),
480                                     TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE,
481                                     policy_handle.ptr());
482  if (TPM_ERROR(result)) {
483    TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
484    return false;
485  }
486  result = Tspi_Policy_SetSecret(
487      policy_handle, TSS_SECRET_MODE_PLAIN, authorization_value.size(),
488      reinterpret_cast<BYTE*>(const_cast<char*>(authorization_value.data())));
489  if (TPM_ERROR(result)) {
490    TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
491    return false;
492  }
493  result =
494      Tspi_Policy_AssignToObject(policy_handle.value(), nv_handle->value());
495  if (TPM_ERROR(result)) {
496    TPM_LOG(ERROR, result) << "Could not set NVRAM object policy.";
497    return false;
498  }
499  return true;
500}
501
502bool TpmNvramImpl::SetCompositePcr0(ScopedTssPcrs* pcr_handle,
503                                    TpmConnection* connection) {
504  TSS_RESULT result = Tspi_Context_CreateObject(
505      connection->GetContext(), TSS_OBJECT_TYPE_PCRS,
506      TSS_PCRS_STRUCT_INFO_SHORT, pcr_handle->ptr());
507  if (TPM_ERROR(result)) {
508    TPM_LOG(ERROR, result) << "Could not acquire PCR object handle";
509    return false;
510  }
511  uint32_t pcr_len;
512  ScopedTssMemory pcr_value(connection->GetContext());
513  result = Tspi_TPM_PcrRead(connection->GetTpm(), kTpmBootPCR, &pcr_len,
514                            pcr_value.ptr());
515  if (TPM_ERROR(result)) {
516    TPM_LOG(ERROR, result) << "Could not read PCR0 value";
517    return false;
518  }
519  result = Tspi_PcrComposite_SetPcrValue(pcr_handle->value(), kTpmBootPCR,
520                                         pcr_len, pcr_value.value());
521  if (TPM_ERROR(result)) {
522    TPM_LOG(ERROR, result) << "Could not set value for PCR0 in PCR handle";
523    return false;
524  }
525  result =
526      Tspi_PcrComposite_SetPcrLocality(pcr_handle->value(), kTpmPCRLocality);
527  if (TPM_ERROR(result)) {
528    TPM_LOG(ERROR, result) << "Could not set locality for PCR0 in PCR handle";
529    return false;
530  }
531  return true;
532}
533
534bool TpmNvramImpl::GetOwnerPassword(std::string* owner_password) {
535  LocalData local_data;
536  if (!local_data_store_->Read(&local_data)) {
537    LOG(ERROR) << "Error reading local data for owner password.";
538    return false;
539  }
540  if (local_data.owner_password().empty()) {
541    LOG(ERROR) << "No owner password present in tpm local_data.";
542    return false;
543  }
544  owner_password->assign(local_data.owner_password());
545  return true;
546}
547
548}  // namespace tpm_manager
549