trunks: implement ManageCCDPwd cr50 command
Add support for VENDOR_CC_MANAGE_CCD_PWD vendor command.
BUG=b:69972868
TEST=unit tests
Change-Id: I3138c6846b460764fa1ae2af3a6a465ce2962f34
Reviewed-on: https://chromium-review.googlesource.com/804600
Commit-Ready: Andrey Pronin <apronin@chromium.org>
Tested-by: Andrey Pronin <apronin@chromium.org>
Reviewed-by: Andrey Pronin <apronin@chromium.org>
diff --git a/trunks/mock_tpm_utility.h b/trunks/mock_tpm_utility.h
index 2126163..e7b7028 100644
--- a/trunks/mock_tpm_utility.h
+++ b/trunks/mock_tpm_utility.h
@@ -157,6 +157,7 @@
TPM_RC(TPM_ALG_ID, AuthorizationDelegate*, std::string*));
MOCK_METHOD0(DeclareTpmFirmwareStable, TPM_RC());
MOCK_METHOD1(GetPublicRSAEndorsementKey, TPM_RC(std::string*));
+ MOCK_METHOD1(ManageCCDPwd, TPM_RC(bool));
};
} // namespace trunks
diff --git a/trunks/tpm_utility.h b/trunks/tpm_utility.h
index 62e5b32..503fb5e 100644
--- a/trunks/tpm_utility.h
+++ b/trunks/tpm_utility.h
@@ -364,6 +364,16 @@
// modulus into |public_key|. Returns TPM_RC_SUCCESS on success.
virtual TPM_RC GetPublicRSAEndorsementKey(std::string* public_key) = 0;
+ // For TPMs that support it: allow setting the CCD password if |allow_pwd|
+ // is true, prohibit otherwise.
+ // Returns the result of sending the appropriate command to the TPM.
+ // For TPMs that don't support it: NOP, always returns TPM_RC_SUCCESS.
+ // Rationale for this behavior: All TPM revisions that need restricting CCD
+ // password implement this command. If the command is not implemented, the
+ // TPM firmware has no notion of restricting the CCD password and doesn't need
+ // a signal to lock things down at login.
+ virtual TPM_RC ManageCCDPwd(bool allow_pwd) = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(TpmUtility);
};
diff --git a/trunks/tpm_utility_impl.cc b/trunks/tpm_utility_impl.cc
index df2ab97..c820ce8 100644
--- a/trunks/tpm_utility_impl.cc
+++ b/trunks/tpm_utility_impl.cc
@@ -55,6 +55,7 @@
const uint32_t kCr50VendorCC = 0x20000000 | 0; /* Vendor Bit Set + 0 */
// Vendor-specific subcommand codes.
const uint16_t kCr50SubcmdInvalidateInactiveRW = 20;
+const uint16_t kCr50SubcmdManageCCDPwd = 33;
// Auth policy used in RSA and ECC templates for EK keys generation.
// From TCG Credential Profile EK 2.0. Section 2.1.5.
@@ -1784,6 +1785,16 @@
return TPM_RC_SUCCESS;
}
+TPM_RC TpmUtilityImpl::ManageCCDPwd(bool allow_pwd) {
+ if (!IsCr50()) {
+ return TPM_RC_SUCCESS;
+ }
+ std::string command_payload(1, allow_pwd ? 1 : 0);
+ std::string response_payload;
+ return Cr50VendorCommand(kCr50SubcmdManageCCDPwd,
+ command_payload, &response_payload);
+}
+
TPM_RC TpmUtilityImpl::SetKnownOwnerPassword(
const std::string& known_owner_password) {
std::unique_ptr<TpmState> tpm_state(factory_.GetTpmState());
diff --git a/trunks/tpm_utility_impl.h b/trunks/tpm_utility_impl.h
index e36887c..8093ee7 100644
--- a/trunks/tpm_utility_impl.h
+++ b/trunks/tpm_utility_impl.h
@@ -169,6 +169,7 @@
std::string* key_blob) override;
TPM_RC DeclareTpmFirmwareStable() override;
TPM_RC GetPublicRSAEndorsementKey(std::string* public_key) override;
+ TPM_RC ManageCCDPwd(bool allow_pwd) override;
private:
friend class TpmUtilityTest;
diff --git a/trunks/tpm_utility_test.cc b/trunks/tpm_utility_test.cc
index a16bb57..9175dec 100644
--- a/trunks/tpm_utility_test.cc
+++ b/trunks/tpm_utility_test.cc
@@ -2355,4 +2355,63 @@
base::HexEncode(public_key.data(), public_key.size()));
}
+TEST_F(TpmUtilityTest, ManageCCDPwdNonCr50) {
+ SetCr50(false);
+ EXPECT_CALL(mock_transceiver_, SendCommandAndWait(_))
+ .Times(0);
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.ManageCCDPwd(true));
+}
+
+TEST_F(TpmUtilityTest, ManageCCDPwdCr50Success) {
+ // A hand-coded kCr50SubcmdManageCCDPwd command (two variants: true and false)
+ // and response.
+ std::string expected_command_true(
+ "\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0D" // size=13
+ "\x20\x00\x00\x00" // code=kCr50VendorCC
+ "\x00\x21" // subcommand=kCr50SubcmdManageCCDPwd
+ "\x01", // value=true
+ 13);
+ std::string expected_command_false(
+ "\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0D" // size=13
+ "\x20\x00\x00\x00" // code=kCr50VendorCC
+ "\x00\x21" // subcommand=kCr50SubcmdManageCCDPwd
+ "\x00", // value=false
+ 13);
+ std::string command_response(
+ "\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0A" // size=10
+ "\x00\x00\x00\x00", // code=TPM_RC_SUCCESS
+ 10);
+ SetCr50(true);
+ EXPECT_CALL(mock_transceiver_, SendCommandAndWait(expected_command_true))
+ .WillOnce(Return(command_response));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.ManageCCDPwd(true));
+ testing::Mock::VerifyAndClearExpectations(&mock_transceiver_);
+ EXPECT_CALL(mock_transceiver_, SendCommandAndWait(expected_command_false))
+ .WillOnce(Return(command_response));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.ManageCCDPwd(false));
+}
+
+TEST_F(TpmUtilityTest, ManageCCDPwdFailure) {
+ // A hand-coded kCr50SubcmdManageCCDPwd command and response.
+ std::string expected_command(
+ "\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0D" // size=13
+ "\x20\x00\x00\x00" // code=kCr50VendorCC
+ "\x00\x21" // subcommand=kCr50SubcmdManageCCDPwd
+ "\x01", // value=true
+ 13);
+ std::string command_response(
+ "\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0A" // size=10
+ "\x00\x00\x01\x01", // code=TPM_RC_FAILURE
+ 10);
+ SetCr50(true);
+ EXPECT_CALL(mock_transceiver_, SendCommandAndWait(expected_command))
+ .WillOnce(Return(command_response));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.ManageCCDPwd(true));
+}
+
} // namespace trunks
diff --git a/trunks/trunks_factory_for_test.cc b/trunks/trunks_factory_for_test.cc
index a9dc4af..aa404b4 100644
--- a/trunks/trunks_factory_for_test.cc
+++ b/trunks/trunks_factory_for_test.cc
@@ -406,6 +406,10 @@
return target_->GetPublicRSAEndorsementKey(public_key);
}
+ TPM_RC ManageCCDPwd(bool allow_pwd) override {
+ return target_->ManageCCDPwd(allow_pwd);
+ }
+
private:
TpmUtility* target_;
};