blob: eda76cd326719b16692cbf4862dadae8abb159c5 [file] [log] [blame]
// Copyright 2014 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.
// trunks_client is a command line tool that supports various TPM operations. It
// does not provide direct access to the trunksd D-Bus interface.
#include <stdio.h>
#include <string>
#include <base/command_line.h>
#include <base/logging.h>
#include <chromeos/syslog_logging.h>
#include "trunks/error_codes.h"
#include "trunks/password_authorization_delegate.h"
#include "trunks/scoped_key_handle.h"
#include "trunks/tpm_utility.h"
#include "trunks/trunks_factory_impl.h"
namespace {
void PrintUsage() {
puts("Options:");
puts(" --help - Prints this message.");
puts(" --startup - Performs startup and self-tests.");
puts(" --clear - Clears the TPM. Use before initializing the TPM.");
puts(" --init_tpm - Initializes a TPM as CrOS firmware does.");
puts(" --own=<owner_password> - Takes ownership of the TPM with the "
"given password");
}
int Startup() {
trunks::TrunksFactoryImpl factory;
factory.GetTpmUtility()->Shutdown();
return factory.GetTpmUtility()->Startup();
}
int Clear() {
trunks::TrunksFactoryImpl factory;
return factory.GetTpmUtility()->Clear();
}
int InitializeTpm() {
trunks::TrunksFactoryImpl factory;
return factory.GetTpmUtility()->InitializeTpm();
}
int TakeOwnership(const std::string& owner_password) {
trunks::TrunksFactoryImpl factory;
trunks::TPM_RC rc;
rc = factory.GetTpmUtility()->TakeOwnership(owner_password,
owner_password,
owner_password);
if (rc) {
LOG(ERROR) << "Error taking ownership: " << trunks::GetErrorString(rc);
return rc;
}
return 0;
}
int SignTest() {
trunks::TrunksFactoryImpl factory;
trunks::TPM_HANDLE signing_key;
trunks::TPM_RC rc;
scoped_ptr<trunks::TpmUtility> utility = factory.GetTpmUtility();
rc = utility->CreateRSAKey(
trunks::TpmUtility::AsymmetricKeyUsage::kSignKey,
"sign",
&signing_key);
if (rc) {
LOG(ERROR) << "Error creating key: " << trunks::GetErrorString(rc);
return rc;
}
trunks::ScopedKeyHandle scoped_key(factory, signing_key);
std::string signature;
rc = utility->Sign(scoped_key.get(),
trunks::TPM_ALG_NULL,
trunks::TPM_ALG_NULL,
"sign",
std::string(32, 'a'),
&signature);
if (rc) {
LOG(ERROR) << "Error signing: " << trunks::GetErrorString(rc);
return rc;
}
rc = utility->Verify(scoped_key.get(),
trunks::TPM_ALG_NULL,
trunks::TPM_ALG_NULL,
std::string(32, 'a'),
signature);
if (rc) {
LOG(ERROR) << "Error verifying: " << trunks::GetErrorString(rc);
return rc;
}
return 0;
}
int DecryptTest() {
trunks::TrunksFactoryImpl factory;
trunks::TPM_HANDLE decrypt_key;
trunks::TPM_RC rc;
scoped_ptr<trunks::TpmUtility> utility = factory.GetTpmUtility();
rc = utility->CreateRSAKey(
trunks::TpmUtility::AsymmetricKeyUsage::kDecryptKey,
"decrypt",
&decrypt_key);
if (rc) {
LOG(ERROR) << "Error creating key: " << trunks::GetErrorString(rc);
return rc;
}
trunks::ScopedKeyHandle scoped_key(factory, decrypt_key);
std::string ciphertext;
rc = utility->AsymmetricEncrypt(scoped_key.get(),
trunks::TPM_ALG_NULL,
trunks::TPM_ALG_NULL,
"plaintext",
&ciphertext);
if (rc) {
LOG(ERROR) << "Error encrypting: " << trunks::GetErrorString(rc);
return rc;
}
std::string plaintext;
rc = utility->AsymmetricDecrypt(scoped_key.get(),
trunks::TPM_ALG_NULL,
trunks::TPM_ALG_NULL,
"decrypt",
ciphertext,
&plaintext);
if (rc) {
LOG(ERROR) << "Error decrypting: " << trunks::GetErrorString(rc);
return rc;
}
CHECK_EQ(plaintext.compare("plaintext"), 0);
return 0;
}
} // namespace
int main(int argc, char **argv) {
CommandLine::Init(argc, argv);
chromeos::InitLog(chromeos::kLogToSyslog | chromeos::kLogToStderr);
CommandLine *cl = CommandLine::ForCurrentProcess();
if (cl->HasSwitch("startup")) {
return Startup();
}
if (cl->HasSwitch("clear")) {
return Clear();
}
if (cl->HasSwitch("init_tpm")) {
return InitializeTpm();
}
if (cl->HasSwitch("help")) {
puts("Trunks Client: A command line tool to access the TPM.");
PrintUsage();
return 0;
}
if (cl->HasSwitch("own")) {
return TakeOwnership(cl->GetSwitchValueASCII("own"));
}
if (cl->HasSwitch("sign_test")) {
return SignTest();
}
if (cl->HasSwitch("decrypt_test")) {
return DecryptTest();
}
puts("Invalid options!");
PrintUsage();
return -1;
}