attestation: Support default and test Verified Access servers BUG=b:69687094 TEST=unit tests Change-Id: I9b4587d155099d9e5f94bfe0a881f73e2acf1a82 Reviewed-on: https://chromium-review.googlesource.com/795216 Commit-Ready: Yves Arrouye <drcrash@chromium.org> Tested-by: Yves Arrouye <drcrash@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org>
diff --git a/attestation/common/interface.proto b/attestation/common/interface.proto index 0bda784..fc024ab 100644 --- a/attestation/common/interface.proto +++ b/attestation/common/interface.proto
@@ -37,6 +37,11 @@ TEST_ACA = 1; } +enum VAType { + DEFAULT_VA = 0; + TEST_VA = 1; +} + message CreateGoogleAttestedKeyRequest { // An arbitrary label which can be used to reference the key later. optional string key_label = 1; @@ -312,6 +317,8 @@ optional bool include_signed_public_key = 5; // The challenge to be signed. optional bytes challenge = 6; + // The VA server that will handle the challenge. + optional VAType va_type = 7; } message SignEnterpriseChallengeReply {
diff --git a/attestation/server/attestation_service.cc b/attestation/server/attestation_service.cc index b7b5fe4..8dac24b 100644 --- a/attestation/server/attestation_service.cc +++ b/attestation/server/attestation_service.cc
@@ -70,7 +70,7 @@ " but provide the right aca_type in requests." #endif -const char kEnterpriseSigningPublicKey[] = +const char kDefaultEnterpriseSigningPublicKey[] = "bf7fefa3a661437b26aed0801db64d7ba8b58875c351d3bdc9f653847d4a67b3" "b67479327724d56aa0f71a3f57c2290fdc1ff05df80589715e381dfbbda2c4ac" "114c30d0a73c5b7b2e22178d26d8b65860aa8dd65e1b3d61a07c81de87c1e7e4" @@ -79,8 +79,7 @@ "69c292c6d9f6f52522333b84ddf9471ffe00f01bf2de5faa1621f967f49e158b" "f2b305360f886826cc6fdbef11a12b2d6002d70d8d1e8f40e0901ff94c203cb2" "01a36a0bd6e83955f14b494f4f2f17c0c826657b85c25ffb8a73599721fa17ab"; - -const char kEnterpriseEncryptionPublicKey[] = +const char kDefaultEnterpriseEncryptionPublicKey[] = "edba5e723da811e41636f792c7a77aef633fbf39b542aa537c93c93eaba7a3b1" "0bc3e484388c13d625ef5573358ec9e7fbeb6baaaa87ca87d93fb61bf5760e29" "6813c435763ed2c81f631e26e3ff1a670261cdc3c39a4640b6bbf4ead3d6587b" @@ -89,13 +88,30 @@ "eb08318611d44daf6044f8527687dc7ce5319b51eae6ab12bee6bd16e59c499e" "fa53d80232ae886c7ee9ad8bc1cbd6e4ac55cb8fa515671f7e7ad66e98769f52" "c3c309f98bf08a3b8fbb0166e97906151b46402217e65c5d01ddac8514340e8b"; - -// This value is opaque; it is proprietary to the system managing the private -// key. In this case the value has been supplied by the enterprise server -// maintainers. -const char kEnterpriseEncryptionPublicKeyID[] = +const char kDefaultEnterpriseEncryptionPublicKeyID[] = "\x00\x4a\xe2\xdc\xae"; +const char kTestEnterpriseSigningPublicKey[] = + "baab3e277518c65b1b98290bb55061df9a50b9f32a4b0ff61c7c61c51e966fcd" + "c891799a39ee0b7278f204a2b45a7e615080ff8f69f668e05adcf3486b319f80" + "f9da814d9b86b16a3e68b4ce514ab5591112838a68dc3bfdcc4043a5aa8de52c" + "ae936847a271971ecaa188172692c13f3b0321239c90559f3b7ba91e66d38ef4" + "db4c75104ac5f2f15e55a463c49753a88e56906b1725fd3f0c1372beb16d4904" + "752c74452b0c9f757ee12877a859dd0666cafaccbfc33fe67d98a89a2c12ef52" + "5e4b16ea8972577dbfc567c2625a3eee6bcaa6cb4939b941f57236d1d57243f8" + "c9766938269a8034d82fbd44044d2ee6a5c7275589afc3790b60280c0689900f"; +const char kTestEnterpriseEncryptionPublicKey[] = + "c0c116e7ded8d7c1e577f9c8fb0d267c3c5c3e3b6800abb0309c248eaa5cd9bf" + "91945132e4bb0111711356a388b756788e20bc1ecc9261ea9bcae8369cfd050e" + "d8dc00b50fbe36d2c1c8a9b335f2e11096be76bebce8b5dcb0dc39ac0fd963b0" + "51474f794d4289cc0c52d0bab451b9e69a43ecd3a84330b0b2de4365c038ffce" + "ec0f1999d789615849c2f3c29d1d9ed42ccb7f330d5b56f40fb7cc6556190c3b" + "698c20d83fb341a442fd69701fe0bdc41bdcf8056ccbc8d9b4275e8e43ec6b63" + "c1ae70d52838dfa90a9cd9e7b6bd88ed3abf4fab444347104e30e635f4f296ac" + "4c91939103e317d0eca5f36c48102e967f176a19a42220f3cf14634b6773be07"; +const char kTestEnterpriseEncryptionPublicKeyID[] = + "\x00\xef\x22\x0f\xb0"; + const size_t kNonceSize = 20; // As per TPM_NONCE definition. const int kNumTemporalValues = 5; @@ -1903,11 +1919,34 @@ } } +const char *AttestationService::GetEnterpriseSigningHexKey(VAType va_type) + const { + return va_type == TEST_VA ? kTestEnterpriseSigningPublicKey : + kDefaultEnterpriseSigningPublicKey; +} + +const char *AttestationService::GetEnterpriseEncryptionHexKey(VAType va_type) + const { + return va_type == TEST_VA ? kTestEnterpriseEncryptionPublicKey : + kDefaultEnterpriseEncryptionPublicKey; +} + +std::string AttestationService::GetEnterpriseEncryptionPublicKeyID( + VAType va_type) const { + return std::string(va_type == TEST_VA ? + kTestEnterpriseEncryptionPublicKeyID : + kDefaultEnterpriseEncryptionPublicKeyID, + arraysize(va_type == TEST_VA ? + kTestEnterpriseEncryptionPublicKeyID : + kDefaultEnterpriseEncryptionPublicKeyID) - 1); +} + bool AttestationService::ValidateEnterpriseChallenge( + VAType va_type, const SignedData& signed_challenge) { const char kExpectedChallengePrefix[] = "EnterpriseKeyChallenge"; if (!crypto_utility_->VerifySignatureUsingHexKey( - kEnterpriseSigningPublicKey, + GetEnterpriseSigningHexKey(va_type), signed_challenge.data(), signed_challenge.signature())) { LOG(ERROR) << __func__ << ": Failed to verify challenge signature."; @@ -1926,6 +1965,7 @@ } bool AttestationService::EncryptEnterpriseKeyInfo( + VAType va_type, const KeyInfo& key_info, EncryptedData* encrypted_data) { std::string serialized; @@ -1933,12 +1973,9 @@ LOG(ERROR) << "Failed to serialize key info."; return false; } - std::string enterprise_key_id( - kEnterpriseEncryptionPublicKeyID, - arraysize(kEnterpriseEncryptionPublicKeyID) - 1); return crypto_utility_->EncryptDataForGoogle( - serialized, kEnterpriseEncryptionPublicKey, - enterprise_key_id, encrypted_data); + serialized, GetEnterpriseEncryptionHexKey(va_type), + GetEnterpriseEncryptionPublicKeyID(va_type), encrypted_data); } void AttestationService::SignEnterpriseChallenge( @@ -1970,7 +2007,7 @@ result->set_status(STATUS_INVALID_PARAMETER); return; } - if (!ValidateEnterpriseChallenge(signed_challenge)) { + if (!ValidateEnterpriseChallenge(request.va_type(), signed_challenge)) { LOG(ERROR) << __func__ << ": Invalid challenge."; result->set_status(STATUS_INVALID_PARAMETER); return; @@ -2007,7 +2044,8 @@ ChallengeResponse response_pb; *response_pb.mutable_challenge() = signed_challenge; response_pb.set_nonce(nonce); - if (!EncryptEnterpriseKeyInfo(key_info, + if (!EncryptEnterpriseKeyInfo(request.va_type(), + key_info, response_pb.mutable_encrypted_key_info())) { LOG(ERROR) << __func__ << ": Failed to encrypt KeyInfo."; result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
diff --git a/attestation/server/attestation_service.h b/attestation/server/attestation_service.h index 50822b4..41b3766 100644 --- a/attestation/server/attestation_service.h +++ b/attestation/server/attestation_service.h
@@ -29,6 +29,7 @@ #include <brillo/bind_lambda.h> #include <brillo/http/http_transport.h> #include <brillo/secure_blob.h> +#include <gtest/gtest_prod.h> #include "attestation/common/attestation_ca.pb.h" #include "attestation/common/crypto_utility.h" @@ -431,12 +432,23 @@ // for enrollment. bool IsVerifiedMode() const; + // Gets the enterprise signing key for |va_type| servers. + const char* GetEnterpriseSigningHexKey(VAType va_type) const; + + // Gets the enterprise encryption key for |va_type| servers. + const char *GetEnterpriseEncryptionHexKey(VAType va_type) const; + + // Gets the enterprise encryption key identifier for |va_type| servers. + std::string GetEnterpriseEncryptionPublicKeyID(VAType va_type) const; + // Validates incoming enterprise challenge data. - bool ValidateEnterpriseChallenge(const SignedData& signed_challenge); + bool ValidateEnterpriseChallenge(VAType va_type, + const SignedData& signed_challenge); // Encrypts a KeyInfo protobuf as required for an enterprise challenge // response. - bool EncryptEnterpriseKeyInfo(const KeyInfo& key_info, + bool EncryptEnterpriseKeyInfo(VAType va_type, + const KeyInfo& key_info, EncryptedData* encrypted_data); // Signs data using the provided key. On success, returns true and fills @@ -503,6 +515,10 @@ base::WeakPtr<AttestationService> GetWeakPtr(); + FRIEND_TEST_ALL_PREFIXES(AttestationServiceEnterpriseTest, + SignEnterpriseChallengeSuccess); + FRIEND_TEST(AttestationServiceTest, SignEnterpriseChallengeSuccess); + // Other than initialization and destruction, these are used only by the // worker thread. CryptoUtility* crypto_utility_{nullptr};
diff --git a/attestation/server/attestation_service_test.cc b/attestation/server/attestation_service_test.cc index 360b5f3..3232a8c 100644 --- a/attestation/server/attestation_service_test.cc +++ b/attestation/server/attestation_service_test.cc
@@ -1849,14 +1849,70 @@ Run(); } +class AttestationServiceEnterpriseTest + : public AttestationServiceTest, + public testing::WithParamInterface<VAType> {}; + +TEST_P(AttestationServiceEnterpriseTest, SignEnterpriseChallengeSuccess) { + KeyInfo key_info = CreateChallengeKeyInfo(); + std::string key_info_str; + key_info.SerializeToString(&key_info_str); + EXPECT_CALL(mock_crypto_utility_, VerifySignatureUsingHexKey( + service_->GetEnterpriseSigningHexKey(GetParam()), _, _)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(mock_crypto_utility_, + EncryptDataForGoogle(key_info_str, + service_->GetEnterpriseEncryptionHexKey(GetParam()), _, _)) + .WillRepeatedly( + DoAll(SetArgPointee<3>(MockEncryptedData(key_info_str)), + Return(true))); + EXPECT_CALL(mock_tpm_utility_, Sign(_, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<2>(std::string("signature")), + Return(true))); + auto callback = [this](const SignEnterpriseChallengeReply& reply) { + EXPECT_EQ(STATUS_SUCCESS, reply.status()); + EXPECT_TRUE(reply.has_challenge_response()); + SignedData signed_data; + EXPECT_TRUE(signed_data.ParseFromString(reply.challenge_response())); + EXPECT_EQ("signature", signed_data.signature()); + ChallengeResponse response_pb; + EXPECT_TRUE(response_pb.ParseFromString(signed_data.data())); + EXPECT_EQ(CreateChallenge("EnterpriseKeyChallenge"), + response_pb.challenge().data()); + KeyInfo key_info = CreateChallengeKeyInfo(); + std::string key_info_str; + key_info.SerializeToString(&key_info_str); + EXPECT_EQ(key_info_str, + response_pb.encrypted_key_info().encrypted_data()); + Quit(); + }; + SignEnterpriseChallengeRequest request; + request.set_va_type(GetParam()); + request.set_username("user"); + request.set_key_label("label"); + request.set_domain(key_info.domain()); + request.set_device_id(key_info.device_id()); + request.set_include_signed_public_key(false); + request.set_challenge(CreateSignedChallenge("EnterpriseKeyChallenge")); + service_->SignEnterpriseChallenge(request, base::Bind(callback)); + Run(); +} + +INSTANTIATE_TEST_CASE_P( + VerifiedAccessType, + AttestationServiceEnterpriseTest, + ::testing::Values(DEFAULT_VA, TEST_VA)); + TEST_F(AttestationServiceTest, SignEnterpriseChallengeSuccess) { KeyInfo key_info = CreateChallengeKeyInfo(); std::string key_info_str; key_info.SerializeToString(&key_info_str); - EXPECT_CALL(mock_crypto_utility_, VerifySignatureUsingHexKey(_, _, _)) + EXPECT_CALL(mock_crypto_utility_, VerifySignatureUsingHexKey( + service_->GetEnterpriseSigningHexKey(DEFAULT_VA), _, _)) .WillRepeatedly(Return(true)); EXPECT_CALL(mock_crypto_utility_, - EncryptDataForGoogle(key_info_str, _, _, _)) + EncryptDataForGoogle(key_info_str, + service_->GetEnterpriseEncryptionHexKey(DEFAULT_VA), _, _)) .WillRepeatedly( DoAll(SetArgPointee<3>(MockEncryptedData(key_info_str)), Return(true)));