blob: 726fd3224bc6aa172a517115a0edcec57391ea39 [file] [log] [blame]
// Copyright 2021 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.
//
#include "trunks/csme/pinweaver_provision_impl.h"
#include <memory>
#include <string>
#include <base/check.h>
#include <base/logging.h>
#include <crypto/sha2.h>
#include "trunks/csme/mei_client.h"
#include "trunks/csme/mei_client_factory.h"
#include "trunks/csme/pinweaver_provision_client.h"
#include "trunks/error_codes.h"
#include "trunks/tpm_state.h"
#include "trunks/tpm_utility.h"
#include "trunks/trunks_factory_impl.h"
namespace trunks {
namespace csme {
bool PinWeaverProvisionImpl::Provision() {
trunks::TrunksFactoryImpl factory;
CHECK(factory.Initialize()) << "Failed to initialize trunks factory.";
std::unique_ptr<trunks::TpmUtility> tpm_utility = factory.GetTpmUtility();
// Persists the salting key in case it's not done yet.
trunks::TPM_RC result = tpm_utility->PrepareForPinWeaver();
if (result) {
LOG(ERROR) << ": Failed to prepare for pinweaver: "
<< trunks::GetErrorString(result);
return false;
}
trunks::TPMT_PUBLIC public_area;
result = tpm_utility->GetKeyPublicArea(trunks::kCsmeSaltingKey, &public_area);
if (result) {
LOG(ERROR) << ": Failed to get public key info: "
<< trunks::GetErrorString(result);
return false;
}
if (public_area.type != trunks::TPM_ALG_ECC) {
LOG(ERROR) << "Unexpected key type (should be trunks::TPM_ALG_ECC): "
<< public_area.type;
return false;
}
const std::string public_key =
StringFrom_TPM2B_ECC_PARAMETER(public_area.unique.ecc.x) +
StringFrom_TPM2B_ECC_PARAMETER(public_area.unique.ecc.y);
const std::string public_key_hash = crypto::SHA256HashString(public_key);
if (!ProvisionSaltingKeyHash(public_key_hash)) {
LOG(ERROR) << "Failed to provision pinweaver-scme salting key.";
return false;
}
return true;
}
bool PinWeaverProvisionImpl::ProvisionSaltingKeyHash(
const std::string& public_key_hash) {
MeiClientFactory mei_client_factory;
PinWeaverProvisionClient client(&mei_client_factory);
bool committed = false;
std::string salting_key_hash;
if (client.GetSaltingKeyHash(&salting_key_hash, &committed) && committed) {
if (salting_key_hash != public_key_hash) {
LOG(ERROR) << "Provisioned salting key hash mismatched.";
return false;
}
LOG(INFO) << "Already provisioned.";
return true;
}
LOG(INFO) << "Not provisioned yet; start provisioning.";
if (!client.SetSaltingKeyHash(public_key_hash)) {
LOG(ERROR) << "Failed to set key hash.";
return false;
}
if (!client.CommitSaltingKeyHash()) {
LOG(ERROR) << "Failed to commit salting key hash.";
return false;
}
return true;
}
bool PinWeaverProvisionImpl::InitOwner() {
trunks::TrunksFactoryImpl factory;
CHECK(factory.Initialize()) << "Failed to initialize trunks factory.";
std::unique_ptr<trunks::TpmState> tpm_state(factory.GetTpmState());
trunks::TPM_RC result = tpm_state->Initialize();
if (result) {
LOG(ERROR) << "Failed to initialize `TpmState`.";
return false;
}
if (tpm_state->IsOwnerPasswordSet()) {
LOG(ERROR) << "Init owner requites empty owner password.";
return false;
}
return InitOwnerInternal();
}
bool PinWeaverProvisionImpl::InitOwnerInternal() {
MeiClientFactory mei_client_factory;
PinWeaverProvisionClient client(&mei_client_factory);
if (!client.InitOwner()) {
LOG(ERROR) << "Failed to init owner.";
return false;
}
return true;
}
} // namespace csme
} // namespace trunks