<commit_before>/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Functions for querying, manipulating and locking rollback indices
 * stored in the TPM NVRAM.
 */

#include "rollback_index.h"

#include "tlcl.h"
#include "tss_constants.h"
#include "utility.h"

/* TPM PCR to use for storing dev mode measurements */
#define DEV_MODE_PCR 0
/* Input digests for PCR extend */
#define DEV_MODE_ON_SHA1_DIGEST ((uint8_t*) "\xbf\x8b\x45\x30\xd8\xd2\x46\xdd" \
                                 "\x74\xac\x53\xa1\x34\x71\xbb\xa1\x79\x41" \
                                 "\xdf\xf7") /* SHA1("\x01") */
#define DEV_MODE_OFF_SHA1_DIGEST ((uint8_t*) "\x5b\xa9\x3c\x9d\xb0\xcf\xf9\x3f"\
                                  "\x52\xb5\x21\xd7\x42\x0e\x43\xf6\xed\xa2" \
                                  "\x78\x4f") /* SHA1("\x00") */

static int g_rollback_recovery_mode = 0;

/* disable MSVC warning on const logical expression (as in } while(0);) */
__pragma(warning (disable: 4127))

#define RETURN_ON_FAILURE(tpm_command) do {             \
    uint32_t result;                                    \
    if ((result = (tpm_command)) != TPM_SUCCESS) {      \
      VBDEBUG(("Rollback: %08x returned by " #tpm_command "\n", (int)result)); \
      return result;                                    \
    }                                                   \
  } while (0)


uint32_t TPMClearAndReenable(void) {
  VBDEBUG(("TPM: Clear and re-enable\n"));
  RETURN_ON_FAILURE(TlclForceClear());
  RETURN_ON_FAILURE(TlclSetEnable());
  RETURN_ON_FAILURE(TlclSetDeactivated(0));

  return TPM_SUCCESS;
}


/* Like TlclWrite(), but checks for write errors due to hitting the 64-write
 * limit and clears the TPM when that happens.  This can only happen when the
 * TPM is unowned, so it is OK to clear it (and we really have no choice).
 * This is not expected to happen frequently, but it could happen.
 */
static uint32_t SafeWrite(uint32_t index, const void* data, uint32_t length) {
  uint32_t result = TlclWrite(index, data, length);
  if (result == TPM_E_MAXNVWRITES) {
    RETURN_ON_FAILURE(TPMClearAndReenable());
    return TlclWrite(index, data, length);
  } else {
    return result;
  }
}


/* Similarly to SafeWrite(), this ensures we don't fail a DefineSpace because
 * we hit the TPM write limit.  This is even less likely to happen than with
 * writes because we only define spaces once at initialization, but we'd rather
 * be paranoid about this.
 */
static uint32_t SafeDefineSpace(uint32_t index, uint32_t perm, uint32_t size) {
  uint32_t result = TlclDefineSpace(index, perm, size);
  if (result == TPM_E_MAXNVWRITES) {
    RETURN_ON_FAILURE(TPMClearAndReenable());
    return TlclDefineSpace(index, perm, size);
  } else {
    return result;
  }
}


/* Functions to read and write firmware and kernel spaces. */
static uint32_t ReadSpaceFirmware(RollbackSpaceFirmware* rsf) {
  return TlclRead(FIRMWARE_NV_INDEX, rsf, sizeof(RollbackSpaceFirmware));
}

static uint32_t WriteSpaceFirmware(const RollbackSpaceFirmware* rsf) {
  return SafeWrite(FIRMWARE_NV_INDEX, rsf, sizeof(RollbackSpaceFirmware));
}

#ifndef DISABLE_ROLLBACK_TPM
static uint32_t ReadSpaceKernel(RollbackSpaceKernel* rsk) {
  return TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
}
#endif

static uint32_t WriteSpaceKernel(const RollbackSpaceKernel* rsk) {
  return SafeWrite(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
}

/* Performs one-time initializations.  Creates the NVRAM spaces, and sets their
 * initial values as needed.  Sets the nvLocked bit and ensures the physical
 * presence command is enabled and locked.
 */
static uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware* rsf,
                                     RollbackSpaceKernel* rsk) {
  static const RollbackSpaceFirmware rsf_init = {
    ROLLBACK_SPACE_FIRMWARE_VERSION, 0, 0, 0};
  static const RollbackSpaceKernel rsk_init = {
    ROLLBACK_SPACE_KERNEL_VERSION, ROLLBACK_SPACE_KERNEL_UID, 0, 0};
  TPM_PERMANENT_FLAGS pflags;
  uint32_t result;

  VBDEBUG(("TPM: One-time initialization\n"));

  result = TlclGetPermanentFlags(&pflags);
  if (result != TPM_SUCCESS)
    return result;

  /* TPM may come from the factory without physical presence finalized.  Fix
   * if necessary. */
  VBDEBUG(("TPM: physicalPresenceLifetimeLock=%d\n",
           pflags.physicalPresenceLifetimeLock));
  if (!pflags.physicalPresenceLifetimeLock) {
    VBDEBUG(("TPM: Finalizing physical presence\n"));
    RETURN_ON_FAILURE(TlclFinalizePhysicalPresence());
  }

  /* The TPM will not enforce the NV authorization restrictions until the
   * execution of a TPM_NV_DefineSpace with the handle of TPM_NV_INDEX_LOCK.
   * Here we create that space if it doesn't already exist. */
  VBDEBUG(("TPM: nvLocked=%d\n", pflags.nvLocked));
  if (!pflags.nvLocked) {
    VBDEBUG(("TPM: Enabling NV locking\n"));
    RETURN_ON_FAILURE(TlclSetNvLocked());
  }

  /* Clear TPM owner, in case the TPM is already owned for some reason. */
  VBDEBUG(("TPM: Clearing owner\n"));
  RETURN_ON_FAILURE(TlclForceClear());

  /* Initializes the firmware and kernel spaces */
  Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware));
  Memcpy(rsk, &rsk_init, sizeof(RollbackSpaceKernel));

  /* Defines and sets firmware and kernel spaces */
  RETURN_ON_FAILURE(SafeDefineSpace(FIRMWARE_NV_INDEX,
                                    TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE,
                                    sizeof(RollbackSpaceFirmware)));
  RETURN_ON_FAILURE(WriteSpaceFirmware(rsf));
  RETURN_ON_FAILURE(SafeDefineSpace(KERNEL_NV_INDEX, TPM_NV_PER_PPWRITE,
                                    sizeof(RollbackSpaceKernel)));
  RETURN_ON_FAILURE(WriteSpaceKernel(rsk));
  return TPM_SUCCESS;
}

<commit_msg>Fix (unfiled, I think) TPM initialization bug.<commit_after>/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Functions for querying, manipulating and locking rollback indices
 * stored in the TPM NVRAM.
 */

#include "rollback_index.h"

#include "tlcl.h"
#include "tss_constants.h"
#include "utility.h"

/* TPM PCR to use for storing dev mode measurements */
#define DEV_MODE_PCR 0
/* Input digests for PCR extend */
#define DEV_MODE_ON_SHA1_DIGEST ((uint8_t*) "\xbf\x8b\x45\x30\xd8\xd2\x46\xdd" \
                                 "\x74\xac\x53\xa1\x34\x71\xbb\xa1\x79\x41" \
                                 "\xdf\xf7") /* SHA1("\x01") */
#define DEV_MODE_OFF_SHA1_DIGEST ((uint8_t*) "\x5b\xa9\x3c\x9d\xb0\xcf\xf9\x3f"\
                                  "\x52\xb5\x21\xd7\x42\x0e\x43\xf6\xed\xa2" \
                                  "\x78\x4f") /* SHA1("\x00") */

static int g_rollback_recovery_mode = 0;

/* disable MSVC warning on const logical expression (as in } while(0);) */
__pragma(warning (disable: 4127))

#define RETURN_ON_FAILURE(tpm_command) do {             \
    uint32_t result;                                    \
    if ((result = (tpm_command)) != TPM_SUCCESS) {      \
      VBDEBUG(("Rollback: %08x returned by " #tpm_command "\n", (int)result)); \
      return result;                                    \
    }                                                   \
  } while (0)


uint32_t TPMClearAndReenable(void) {
  VBDEBUG(("TPM: Clear and re-enable\n"));
  RETURN_ON_FAILURE(TlclForceClear());
  RETURN_ON_FAILURE(TlclSetEnable());
  RETURN_ON_FAILURE(TlclSetDeactivated(0));

  return TPM_SUCCESS;
}


/* Like TlclWrite(), but checks for write errors due to hitting the 64-write
 * limit and clears the TPM when that happens.  This can only happen when the
 * TPM is unowned, so it is OK to clear it (and we really have no choice).
 * This is not expected to happen frequently, but it could happen.
 */
static uint32_t SafeWrite(uint32_t index, const void* data, uint32_t length) {
  uint32_t result = TlclWrite(index, data, length);
  if (result == TPM_E_MAXNVWRITES) {
    RETURN_ON_FAILURE(TPMClearAndReenable());
    return TlclWrite(index, data, length);
  } else {
    return result;
  }
}


/* Similarly to SafeWrite(), this ensures we don't fail a DefineSpace because
 * we hit the TPM write limit.  This is even less likely to happen than with
 * writes because we only define spaces once at initialization, but we'd rather
 * be paranoid about this.
 */
static uint32_t SafeDefineSpace(uint32_t index, uint32_t perm, uint32_t size) {
  uint32_t result = TlclDefineSpace(index, perm, size);
  if (result == TPM_E_MAXNVWRITES) {
    RETURN_ON_FAILURE(TPMClearAndReenable());
    return TlclDefineSpace(index, perm, size);
  } else {
    return result;
  }
}


/* Functions to read and write firmware and kernel spaces. */
static uint32_t ReadSpaceFirmware(RollbackSpaceFirmware* rsf) {
  return TlclRead(FIRMWARE_NV_INDEX, rsf, sizeof(RollbackSpaceFirmware));
}

static uint32_t WriteSpaceFirmware(const RollbackSpaceFirmware* rsf) {
  return SafeWrite(FIRMWARE_NV_INDEX, rsf, sizeof(RollbackSpaceFirmware));
}

#ifndef DISABLE_ROLLBACK_TPM
static uint32_t ReadSpaceKernel(RollbackSpaceKernel* rsk) {
  return TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
}
#endif

static uint32_t WriteSpaceKernel(const RollbackSpaceKernel* rsk) {
  return SafeWrite(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
}

/* Performs one-time initializations.  Creates the NVRAM spaces, and sets their
 * initial values as needed.  Sets the nvLocked bit and ensures the physical
 * presence command is enabled and locked.
 */
static uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware* rsf,
                                     RollbackSpaceKernel* rsk) {
  static const RollbackSpaceFirmware rsf_init = {
    ROLLBACK_SPACE_FIRMWARE_VERSION, 0, 0, 0};
  static const RollbackSpaceKernel rsk_init = {
    ROLLBACK_SPACE_KERNEL_VERSION, ROLLBACK_SPACE_KERNEL_UID, 0, 0};
  TPM_PERMANENT_FLAGS pflags;
  uint32_t result;

  VBDEBUG(("TPM: One-time initialization\n"));

  result = TlclGetPermanentFlags(&pflags);
  if (result != TPM_SUCCESS)
    return result;

  /* TPM may come from the factory without physical presence finalized.  Fix
   * if necessary. */
  VBDEBUG(("TPM: physicalPresenceLifetimeLock=%d\n",
           pflags.physicalPresenceLifetimeLock));
  if (!pflags.physicalPresenceLifetimeLock) {
    VBDEBUG(("TPM: Finalizing physical presence\n"));
    RETURN_ON_FAILURE(TlclFinalizePhysicalPresence());
  }

  /* The TPM will not enforce the NV authorization restrictions until the
   * execution of a TPM_NV_DefineSpace with the handle of TPM_NV_INDEX_LOCK.
   * Here we create that space if it doesn't already exist. */
  VBDEBUG(("TPM: nvLocked=%d\n", pflags.nvLocked));
  if (!pflags.nvLocked) {
    VBDEBUG(("TPM: Enabling NV locking\n"));
    RETURN_ON_FAILURE(TlclSetNvLocked());
  }

  /* Clear TPM owner, in case the TPM is already owned for some reason. */
  VBDEBUG(("TPM: Clearing owner\n"));
  RETURN_ON_FAILURE(TPMClearAndReenable());

  /* Initializes the firmware and kernel spaces */
  Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware));
  Memcpy(rsk, &rsk_init, sizeof(RollbackSpaceKernel));

  /* Defines and sets firmware and kernel spaces */
  RETURN_ON_FAILURE(SafeDefineSpace(FIRMWARE_NV_INDEX,
                                    TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE,
                                    sizeof(RollbackSpaceFirmware)));
  RETURN_ON_FAILURE(WriteSpaceFirmware(rsf));
  RETURN_ON_FAILURE(SafeDefineSpace(KERNEL_NV_INDEX, TPM_NV_PER_PPWRITE,
                                    sizeof(RollbackSpaceKernel)));
  RETURN_ON_FAILURE(WriteSpaceKernel(rsk));
  return TPM_SUCCESS;
}


{'fraction_non_alphanumeric': 0.09901494565217392, 'fraction_numerical': 0.01919157608695652, 'mean_word_length': 3.2919096209912535, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2948756', 'n_tokens_mistral': 4066, 'n_tokens_neox': 3870, 'n_words': 994}