Commit fab5ba9e authored by Josh Nohle's avatar Josh Nohle Committed by Commit Bot

Revert "Use existing kUserKeyPair keys during key creation, if possible."

This reverts commit 657a8c53.

Reason for revert: ASAN errors; container overflow

Original change's description:
> Use existing kUserKeyPair keys during key creation, if possible.
> 
> In CyptAuth v2 Enrollment, the user key pair--also known as
> CryptAuthKeyBundle::Name::kUserKeyPair or "PublicKey"--has special
> standing in order to 1) accommodate any existing key from v1 Enrollment
> and 2) enforce that the key is not rotated. Only one user key pair
> should exist in its key bundle, and it should be an active, P-256 key
> with handle "device_key".
> 
> It is possible that CryptAuth could request the creation of a new user
> key pair even if the client sends information about an existing key in
> the SyncKeysRequest. If this happens, the client should re-use the
> existing user key pair key material when creating a new key. At the end
> of the enrollment flow, the existing key will be replaced with this new
> key that has the same public/private keys, but possibly with a new key
> directive.
> 
> It might seem more efficient to simply ignore the key-creation request,
> but the method outlined above natually fits into the enrollment flow,
> the key directive will be updated, and the client will be able to
> provide CryptAuth with an EnrollKeys request, which it might be
> expected.
> 
> Bug: 899080
> Change-Id: I3a4a63aa902090698ecb619bc7af78ff1e790c23
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1504121
> Commit-Queue: Josh Nohle <nohle@chromium.org>
> Reviewed-by: Kyle Horimoto <khorimoto@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#638327}

TBR=khorimoto@chromium.org,nohle@chromium.org

Change-Id: Ida02d62899eecc6a391e05b34bf576ff12e9541f
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 899080
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1507279
Commit-Queue: Josh Nohle <nohle@chromium.org>
Reviewed-by: default avatarJames Hawkins <jhawkins@chromium.org>
Cr-Commit-Position: refs/heads/master@{#638393}
parent c99f13fc
......@@ -116,11 +116,7 @@ std::ostream& operator<<(
stream << "[Error: KeyActions do not specify an active key]";
break;
case ResultCode::kErrorKeyCreationKeyTypeNotSupported:
stream << "[Error: Key-creation instructions specify unsupported "
<< "KeyType]";
break;
case ResultCode::kErrorUserKeyPairCreationInstructionsInvalid:
stream << "[Error: Key-creation instructions for user key pair invalid]";
stream << "[Error: KeyCreation instructions specify unsupported KeyType]";
break;
case ResultCode::kErrorSymmetricKeyCreationMissingServerDiffieHellman:
stream << "[Error: Cannot create symmetric key; missing server "
......
......@@ -79,9 +79,6 @@ class CryptAuthEnrollmentResult {
kErrorKeyActionsDoNotSpecifyAnActiveKey,
// KeyCreation instructions specify an unsupported KeyType.
kErrorKeyCreationKeyTypeNotSupported,
// Invalid key-creation instructions for user key pair. It must be P256 and
// active.
kErrorUserKeyPairCreationInstructionsInvalid,
// Cannot create a symmetric key without the server's Diffie-Hellman key.
kErrorSymmetricKeyCreationMissingServerDiffieHellman,
// Failed to compute at least one key proof.
......
......@@ -14,22 +14,6 @@ CryptAuthKeyCreator::CreateKeyData::CreateKeyData(
base::Optional<std::string> handle)
: status(status), type(type), handle(handle) {}
CryptAuthKeyCreator::CreateKeyData::CreateKeyData(
CryptAuthKey::Status status,
cryptauthv2::KeyType type,
const std::string& handle,
const std::string& public_key,
const std::string& private_key)
: status(status),
type(type),
handle(handle),
public_key(public_key),
private_key(private_key) {
DCHECK(!handle.empty());
DCHECK(!public_key.empty());
DCHECK(!private_key.empty());
}
CryptAuthKeyCreator::CreateKeyData::~CreateKeyData() = default;
CryptAuthKeyCreator::CreateKeyData::CreateKeyData(const CreateKeyData&) =
......
......@@ -49,27 +49,12 @@ class CryptAuthKeyCreator {
CreateKeyData(CryptAuthKey::Status status,
cryptauthv2::KeyType type,
base::Optional<std::string> handle = base::nullopt);
// Special constructor needed to handle existing user key pair. The input
// strings cannot be empty.
CreateKeyData(CryptAuthKey::Status status,
cryptauthv2::KeyType type,
const std::string& handle,
const std::string& public_key,
const std::string& private_key);
~CreateKeyData();
CreateKeyData(const CreateKeyData&);
CryptAuthKey::Status status;
cryptauthv2::KeyType type;
base::Optional<std::string> handle;
// Special data needed to handle existing user key pair. If these are both
// non-empty strings and the key type is asymmetric, then the key creator
// will bypass the standard key creation and simply return
// CryptAuthKey(|public_key|, |private_key|, |status|, |type|, |handle|).
base::Optional<std::string> public_key;
base::Optional<std::string> private_key;
};
CryptAuthKeyCreator();
......
......@@ -4,13 +4,21 @@
#include "chromeos/services/device_sync/cryptauth_key_creator_impl.h"
#include <memory>
#include <string>
#include <utility>
#include "base/base64.h"
#include "base/bind.h"
#include "base/containers/flat_map.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "base/optional.h"
#include "base/strings/string_util.h"
#include "chromeos/components/multidevice/logging/logging.h"
#include "chromeos/components/multidevice/secure_message_delegate_impl.h"
#include "chromeos/services/device_sync/cryptauth_constants.h"
#include "chromeos/services/device_sync/cryptauth_key.h"
#include "chromeos/services/device_sync/proto/cryptauth_common.pb.h"
#include "crypto/hkdf.h"
#include "crypto/random.h"
......@@ -157,41 +165,29 @@ void CryptAuthKeyCreatorImpl::OnDiffieHellmanHandshakeSecretDerived(
void CryptAuthKeyCreatorImpl::StartKeyCreation() {
for (const auto& key_to_create : keys_to_create_) {
const CryptAuthKeyBundle::Name& bundle_name = key_to_create.first;
const CreateKeyData& key_data = key_to_create.second;
// If the key to create is symmetric, derive a symmetric key from the
// Diffie-Hellman handshake secrect using HKDF. The CryptAuth v2
// Enrollment protocol specifies that the salt should be "CryptAuth
// Enrollment" and the info should be the key handle. This process is
// synchronous, unlike SecureMessageDelegate calls.
if (IsValidSymmetricKeyType(key_data.type)) {
std::string handle =
key_data.handle ? *key_data.handle : CreateRandomHandle();
std::string derived_symmetric_key_material =
crypto::HkdfSha256(dh_handshake_secret_->symmetric_key(),
kCryptAuthSymmetricKeyDerivationSalt, handle,
NumBytesForSymmetricKeyType(key_data.type));
OnSymmetricKeyDerived(bundle_name, derived_symmetric_key_material,
if (IsValidSymmetricKeyType(key_to_create.second.type)) {
std::string handle = key_to_create.second.handle.has_value()
? *key_to_create.second.handle
: CreateRandomHandle();
std::string derived_symmetric_key_material = crypto::HkdfSha256(
dh_handshake_secret_->symmetric_key(),
kCryptAuthSymmetricKeyDerivationSalt, handle,
NumBytesForSymmetricKeyType(key_to_create.second.type));
OnSymmetricKeyDerived(key_to_create.first, derived_symmetric_key_material,
handle);
} else {
DCHECK(IsValidAsymmetricKeyType(key_to_create.second.type));
continue;
secure_message_delegate_->GenerateKeyPair(
base::Bind(&CryptAuthKeyCreatorImpl::OnAsymmetricKeyPairGenerated,
base::Unretained(this), key_to_create.first));
}
DCHECK(IsValidAsymmetricKeyType(key_data.type));
// If the key material was explicitly set in CreateKeyData, bypass the
// standard key creation.
if (key_data.public_key && key_data.private_key) {
OnAsymmetricKeyPairGenerated(bundle_name, *key_data.public_key,
*key_data.private_key);
continue;
}
secure_message_delegate_->GenerateKeyPair(
base::Bind(&CryptAuthKeyCreatorImpl::OnAsymmetricKeyPairGenerated,
base::Unretained(this), key_to_create.first));
}
}
......
......@@ -5,6 +5,8 @@
#ifndef CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_CREATOR_IMPL_H_
#define CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_CREATOR_IMPL_H_
#include "chromeos/services/device_sync/cryptauth_key_creator.h"
#include <memory>
#include <string>
#include <utility>
......@@ -16,7 +18,6 @@
#include "base/optional.h"
#include "chromeos/services/device_sync/cryptauth_key.h"
#include "chromeos/services/device_sync/cryptauth_key_bundle.h"
#include "chromeos/services/device_sync/cryptauth_key_creator.h"
namespace chromeos {
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/services/device_sync/cryptauth_key_creator_impl.h"
#include <memory>
#include <string>
#include <utility>
......@@ -16,7 +18,6 @@
#include "chromeos/services/device_sync/cryptauth_key.h"
#include "chromeos/services/device_sync/cryptauth_key_bundle.h"
#include "chromeos/services/device_sync/cryptauth_key_creator.h"
#include "chromeos/services/device_sync/cryptauth_key_creator_impl.h"
#include "chromeos/services/device_sync/proto/cryptauth_common.pb.h"
#include "crypto/hkdf.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -32,19 +33,15 @@ const char kFakeClientEphemeralDhPublicKeyMaterial[] = "client_ephemeral_dh";
const char kFakeAsymmetricKeyHandle[] = "asymmetric_key_handle";
const char kFakePublicKeyMaterial[] = "public_key";
const char kFakeSymmetricKeyHandle[] = "symmetric_key_handle";
const char kFakeProvidedPublicKeyMaterial[] = "provided_public_key";
const char kFakeProvidedPrivateKeyMaterial[] = "provided_private_key";
size_t NumBytesForSymmetricKeyType(cryptauthv2::KeyType key_type) {
switch (key_type) {
case cryptauthv2::KeyType::RAW128:
return 16u;
case cryptauthv2::KeyType::RAW256:
return 32u;
default:
NOTREACHED();
return 0u;
}
void VerifyCreatedKeysCallback(
const base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey>&
expected_new_keys,
const base::Optional<CryptAuthKey>& expected_client_ephemeral_dh,
const base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey>& new_keys,
const base::Optional<CryptAuthKey>& client_ephemeral_dh) {
EXPECT_EQ(expected_client_ephemeral_dh, client_ephemeral_dh);
EXPECT_EQ(expected_new_keys, new_keys);
}
class FakeSecureMessageDelegateFactory
......@@ -74,19 +71,12 @@ class FakeSecureMessageDelegateFactory
class DeviceSyncCryptAuthKeyCreatorImplTest : public testing::Test {
protected:
DeviceSyncCryptAuthKeyCreatorImplTest()
: fake_secure_message_delegate_factory_(
std::make_unique<FakeSecureMessageDelegateFactory>()),
fake_server_ephemeral_dh_(CryptAuthKey(
kFakeServerEphemeralDhPublicKeyMaterial,
fake_secure_message_delegate()->GetPrivateKeyForPublicKey(
kFakeServerEphemeralDhPublicKeyMaterial),
CryptAuthKey::Status::kActive,
cryptauthv2::KeyType::P256)) {}
DeviceSyncCryptAuthKeyCreatorImplTest() = default;
~DeviceSyncCryptAuthKeyCreatorImplTest() override = default;
void SetUp() override {
fake_secure_message_delegate_factory_ =
std::make_unique<FakeSecureMessageDelegateFactory>();
multidevice::SecureMessageDelegateImpl::Factory::SetInstanceForTesting(
fake_secure_message_delegate_factory_.get());
......@@ -98,80 +88,30 @@ class DeviceSyncCryptAuthKeyCreatorImplTest : public testing::Test {
nullptr);
}
void CallCreateKeys(
const base::flat_map<CryptAuthKeyBundle::Name,
CryptAuthKeyCreator::CreateKeyData>& keys_to_create,
const base::Optional<CryptAuthKey>& server_ephemeral_dh) {
key_creator_->CreateKeys(
keys_to_create, server_ephemeral_dh,
base::BindOnce(&DeviceSyncCryptAuthKeyCreatorImplTest::OnKeysCreated,
base::Unretained(this)));
}
void VerifyKeyCreation(
const base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey>&
expected_new_keys,
const base::Optional<CryptAuthKey>& expected_client_ephemeral_dh) {
EXPECT_TRUE(new_keys_);
EXPECT_TRUE(client_ephemeral_dh_);
EXPECT_EQ(expected_new_keys, *new_keys_);
EXPECT_EQ(expected_client_ephemeral_dh, *client_ephemeral_dh_);
}
std::string DeriveSecret(const CryptAuthKey& server_ephemeral_dh,
const CryptAuthKey& client_ephemeral_dh) {
CryptAuthKey DeriveSecret(
const base::Optional<CryptAuthKey>& server_ephemeral_dh,
const base::Optional<CryptAuthKey>& client_ephemeral_dh) {
std::string derived_key;
fake_secure_message_delegate()->DeriveKey(
client_ephemeral_dh.private_key(), server_ephemeral_dh.public_key(),
client_ephemeral_dh->private_key(), server_ephemeral_dh->public_key(),
base::Bind([](std::string* derived_key,
const std::string& key) { *derived_key = key; },
&derived_key));
return derived_key;
return CryptAuthKey(derived_key, CryptAuthKey::Status::kActive,
cryptauthv2::KeyType::RAW256);
}
CryptAuthKey DeriveSymmetricKey(
const CryptAuthKeyBundle::Name& bundle_name,
const CryptAuthKeyCreator::CreateKeyData& key_to_create,
const CryptAuthKey& client_ephemeral_dh) {
std::string expected_handshake_secret =
DeriveSecret(fake_server_ephemeral_dh_, client_ephemeral_dh);
std::string expected_symmetric_key_material = crypto::HkdfSha256(
expected_handshake_secret, kCryptAuthSymmetricKeyDerivationSalt,
key_to_create.handle ? *key_to_create.handle : "",
NumBytesForSymmetricKeyType(key_to_create.type));
return CryptAuthKey(expected_symmetric_key_material, key_to_create.status,
key_to_create.type, key_to_create.handle);
}
CryptAuthKeyCreator* key_creator() { return key_creator_.get(); }
multidevice::FakeSecureMessageDelegate* fake_secure_message_delegate() {
return fake_secure_message_delegate_factory_->instance();
}
const CryptAuthKey& fake_server_ephemeral_dh() {
return fake_server_ephemeral_dh_;
}
private:
void OnKeysCreated(
const base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey>& new_keys,
const base::Optional<CryptAuthKey>& client_ephemeral_dh) {
new_keys_ = new_keys;
client_ephemeral_dh_ = client_ephemeral_dh;
}
std::unique_ptr<FakeSecureMessageDelegateFactory>
fake_secure_message_delegate_factory_;
std::unique_ptr<CryptAuthKeyCreator> key_creator_;
CryptAuthKey fake_server_ephemeral_dh_;
// A null value (for the outermost Optional) indicates that OnKeysCreated()
// was not called.
base::Optional<base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey>>
new_keys_;
base::Optional<base::Optional<CryptAuthKey>> client_ephemeral_dh_;
std::unique_ptr<CryptAuthKeyCreator> key_creator_;
DISALLOW_COPY_AND_ASSIGN(DeviceSyncCryptAuthKeyCreatorImplTest);
};
......@@ -196,82 +136,53 @@ TEST_F(DeviceSyncCryptAuthKeyCreatorImplTest, AsymmetricKeyCreation) {
fake_secure_message_delegate()->set_next_public_key(kFakePublicKeyMaterial);
CallCreateKeys(keys_to_create, base::nullopt /* fake_server_ephemeral_dh */);
VerifyKeyCreation(expected_new_keys,
base::nullopt /* expected_client_ephemeral_dh */);
key_creator()->CreateKeys(
keys_to_create, base::nullopt /* fake_server_ephemeral_dh */,
base::BindOnce(VerifyCreatedKeysCallback, expected_new_keys,
base::nullopt /* expected_client_ephemeral_dh */));
}
TEST_F(DeviceSyncCryptAuthKeyCreatorImplTest, SymmetricKeyCreation) {
CryptAuthKeyCreator::CreateKeyData symmetric_key_to_create(
CryptAuthKey::Status::kActive, cryptauthv2::KeyType::RAW256,
kFakeSymmetricKeyHandle);
base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKeyCreator::CreateKeyData>
keys_to_create = {{CryptAuthKeyBundle::Name::kLegacyMasterKey,
symmetric_key_to_create}};
CryptAuthKey expected_client_ephemeral_dh(
kFakeClientEphemeralDhPublicKeyMaterial,
fake_secure_message_delegate()->GetPrivateKeyForPublicKey(
kFakeClientEphemeralDhPublicKeyMaterial),
CryptAuthKey::Status::kActive, cryptauthv2::KeyType::P256);
CryptAuthKey expected_symmetric_key =
DeriveSymmetricKey(CryptAuthKeyBundle::Name::kLegacyMasterKey,
symmetric_key_to_create, expected_client_ephemeral_dh);
base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey> expected_new_keys = {
{CryptAuthKeyBundle::Name::kLegacyMasterKey, expected_symmetric_key}};
fake_secure_message_delegate()->set_next_public_key(
kFakeClientEphemeralDhPublicKeyMaterial);
CallCreateKeys(keys_to_create, fake_server_ephemeral_dh());
VerifyKeyCreation(expected_new_keys, expected_client_ephemeral_dh);
}
TEST_F(DeviceSyncCryptAuthKeyCreatorImplTest,
MultipleKeyCreation_KeyMaterialProvidedForAsymmetricKey) {
CryptAuthKeyCreator::CreateKeyData symmetric_key_to_create(
CryptAuthKey::Status::kActive, cryptauthv2::KeyType::RAW256,
kFakeSymmetricKeyHandle);
base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKeyCreator::CreateKeyData>
keys_to_create = {
{CryptAuthKeyBundle::Name::kUserKeyPair,
CryptAuthKeyCreator::CreateKeyData(
CryptAuthKey::Status::kActive, cryptauthv2::KeyType::P256,
kFakeAsymmetricKeyHandle, kFakeProvidedPublicKeyMaterial,
kFakeProvidedPrivateKeyMaterial)},
{CryptAuthKeyBundle::Name::kLegacyMasterKey,
symmetric_key_to_create}};
CryptAuthKey expected_client_ephemeral_dh(
kFakeClientEphemeralDhPublicKeyMaterial,
fake_secure_message_delegate()->GetPrivateKeyForPublicKey(
kFakeClientEphemeralDhPublicKeyMaterial),
CryptAuthKey::Status::kActive, cryptauthv2::KeyType::P256);
CryptAuthKey expected_asymmetric_key(
kFakeProvidedPublicKeyMaterial, kFakeProvidedPrivateKeyMaterial,
CryptAuthKey::Status::kActive, cryptauthv2::KeyType::P256,
kFakeAsymmetricKeyHandle);
CryptAuthKey expected_symmetric_key =
DeriveSymmetricKey(CryptAuthKeyBundle::Name::kLegacyMasterKey,
symmetric_key_to_create, expected_client_ephemeral_dh);
CryptAuthKeyCreator::CreateKeyData(CryptAuthKey::Status::kActive,
cryptauthv2::KeyType::RAW256,
kFakeSymmetricKeyHandle)}};
base::Optional<CryptAuthKey> fake_server_ephemeral_dh =
CryptAuthKey(kFakeServerEphemeralDhPublicKeyMaterial,
fake_secure_message_delegate()->GetPrivateKeyForPublicKey(
kFakeServerEphemeralDhPublicKeyMaterial),
CryptAuthKey::Status::kActive, cryptauthv2::KeyType::P256);
base::Optional<CryptAuthKey> expected_client_ephemeral_dh =
CryptAuthKey(kFakeClientEphemeralDhPublicKeyMaterial,
fake_secure_message_delegate()->GetPrivateKeyForPublicKey(
kFakeClientEphemeralDhPublicKeyMaterial),
CryptAuthKey::Status::kActive, cryptauthv2::KeyType::P256);
CryptAuthKey expected_handshake_secret =
DeriveSecret(fake_server_ephemeral_dh, expected_client_ephemeral_dh);
std::string expected_symmetric_key_material =
crypto::HkdfSha256(expected_handshake_secret.symmetric_key(),
kCryptAuthSymmetricKeyDerivationSalt,
kFakeSymmetricKeyHandle, 32u /* derived_key_size */);
CryptAuthKey expected_symmetric_key(
expected_symmetric_key_material, CryptAuthKey::Status::kActive,
cryptauthv2::KeyType::RAW256, kFakeSymmetricKeyHandle);
base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey> expected_new_keys = {
{CryptAuthKeyBundle::Name::kUserKeyPair, expected_asymmetric_key},
{CryptAuthKeyBundle::Name::kLegacyMasterKey, expected_symmetric_key}};
{CryptAuthKeyBundle::Name::kUserKeyPair, expected_symmetric_key}};
// There is no need to generate an asymmetric key for kUserKeyPair since we
// passed in the key material to CreateKeyData.
fake_secure_message_delegate()->set_next_public_key(
kFakeClientEphemeralDhPublicKeyMaterial);
CallCreateKeys(keys_to_create, fake_server_ephemeral_dh());
VerifyKeyCreation(expected_new_keys, expected_client_ephemeral_dh);
key_creator()->CreateKeys(
keys_to_create, fake_server_ephemeral_dh,
base::BindOnce(VerifyCreatedKeysCallback, expected_new_keys,
expected_client_ephemeral_dh));
}
} // namespace device_sync
......
......@@ -254,59 +254,48 @@ bool IsSupportedKeyType(const cryptauthv2::KeyType& key_type) {
key_type == cryptauthv2::KeyType::P256;
}
// The key bundle kUserKeyPair has special standing in order to 1) accommodate
// any existing key from v1 Enrollment and 2) enforce that the key is not
// rotated. As such, only one user key pair should exist in the key bundle, and
// it should be an active, P-256 key with handle
// kCryptAuthFixedUserKeyPairHandle.
//
// It is possible that CryptAuth could request the creation of a new user key
// pair even if the client sends information about an existing key in the
// SyncKeysRequest. If this happens, the client should re-use the existing user
// key pair key material when creating a new key. At the end of the enrollment
// flow, the existing key will be replaced with this new key that has the same
// public/private keys.
//
// Returns an error code if the key-creation instructions are invalid and null
// otherwise.
base::Optional<CryptAuthEnrollmentResult::ResultCode>
ProcessNewUserKeyPairInstructions(
CryptAuthKey::Status status,
cryptauthv2::KeyType type,
const CryptAuthKey* current_active_key,
base::Optional<CryptAuthKeyCreator::CreateKeyData>* new_key_to_create) {
if (type != cryptauthv2::KeyType::P256) {
PA_LOG(ERROR) << "User key pair must have KeyType P256.";
ProcessKeyCreationInstructions(
const CryptAuthKeyBundle::Name& bundle_name,
const SyncSingleKeyResponse& single_key_response,
const std::string& server_ephemeral_dh,
base::Optional<CryptAuthKeyCreator::CreateKeyData>* new_key_to_create,
base::Optional<cryptauthv2::KeyDirective>* new_key_directive) {
if (single_key_response.key_creation() == SyncSingleKeyResponse::NONE)
return base::nullopt;
if (!IsSupportedKeyType(single_key_response.key_type())) {
PA_LOG(ERROR) << "KeyType " << single_key_response.key_type() << " "
<< "not supported.";
return CryptAuthEnrollmentResult::ResultCode::
kErrorUserKeyPairCreationInstructionsInvalid;
kErrorKeyCreationKeyTypeNotSupported;
}
// Because no more than one user key pair can exist in the bundle, the newly
// created key must be active.
if (status != CryptAuthKey::Status::kActive) {
PA_LOG(ERROR) << "New user key pair must be active.";
// Symmetric keys cannot be created without the server's Diffie-Hellman key.
if (server_ephemeral_dh.empty() &&
(single_key_response.key_type() == cryptauthv2::KeyType::RAW128 ||
single_key_response.key_type() == cryptauthv2::KeyType::RAW256)) {
PA_LOG(ERROR)
<< "Missing server's Diffie-Hellman key. Cannot create symmetric keys.";
return CryptAuthEnrollmentResult::ResultCode::
kErrorUserKeyPairCreationInstructionsInvalid;
kErrorSymmetricKeyCreationMissingServerDiffieHellman;
}
// If a user key pair already exists in the registry, reuse the same key data.
if (current_active_key && current_active_key->IsAsymmetricKey() &&
!current_active_key->private_key().empty()) {
PA_LOG(WARNING) << "Received request to create new user key pair while one "
<< "already exists in the key registry. Reusing existing "
<< "key material.";
// CryptAuth demands that the key in the kUserKeyPair bundle has a fixed
// handle name. For other key bundles, do not specify a handle name; let
// CryptAuthKey generate a handle for us.
base::Optional<std::string> new_key_handle;
if (bundle_name == CryptAuthKeyBundle::Name::kUserKeyPair)
new_key_handle = kCryptAuthFixedUserKeyPairHandle;
*new_key_to_create = CryptAuthKeyCreator::CreateKeyData(
status, type, kCryptAuthFixedUserKeyPairHandle,
current_active_key->public_key(), current_active_key->private_key());
return base::nullopt;
}
// If there is no user key pair in the registry, then the user has never
// successfully enrolled via v1 or v2 Enrollment. Generate a new key pair.
*new_key_to_create = CryptAuthKeyCreator::CreateKeyData(
status, type, kCryptAuthFixedUserKeyPairHandle);
ConvertKeyCreationToKeyStatus(single_key_response.key_creation()),
single_key_response.key_type(), new_key_handle);
if (single_key_response.has_key_directive())
*new_key_directive = single_key_response.key_directive();
return base::nullopt;
}
......@@ -631,51 +620,6 @@ CryptAuthV2EnrollerImpl::ProcessSingleKeyResponses(
return error_code;
}
base::Optional<CryptAuthEnrollmentResult::ResultCode>
CryptAuthV2EnrollerImpl::ProcessKeyCreationInstructions(
const CryptAuthKeyBundle::Name& bundle_name,
const SyncSingleKeyResponse& single_key_response,
const std::string& server_ephemeral_dh,
base::Optional<CryptAuthKeyCreator::CreateKeyData>* new_key_to_create,
base::Optional<cryptauthv2::KeyDirective>* new_key_directive) {
if (single_key_response.key_creation() == SyncSingleKeyResponse::NONE)
return base::nullopt;
CryptAuthKey::Status status =
ConvertKeyCreationToKeyStatus(single_key_response.key_creation());
cryptauthv2::KeyType type = single_key_response.key_type();
if (!IsSupportedKeyType(type)) {
PA_LOG(ERROR) << "KeyType " << type << " not supported.";
return CryptAuthEnrollmentResult::ResultCode::
kErrorKeyCreationKeyTypeNotSupported;
}
// Symmetric keys cannot be created without the server's Diffie-Hellman key.
if (server_ephemeral_dh.empty() && (type == cryptauthv2::KeyType::RAW128 ||
type == cryptauthv2::KeyType::RAW256)) {
PA_LOG(ERROR)
<< "Missing server's Diffie-Hellman key. Cannot create symmetric keys.";
return CryptAuthEnrollmentResult::ResultCode::
kErrorSymmetricKeyCreationMissingServerDiffieHellman;
}
if (single_key_response.has_key_directive())
*new_key_directive = single_key_response.key_directive();
// Handle the user key pair special case separately below.
if (bundle_name != CryptAuthKeyBundle::Name::kUserKeyPair) {
*new_key_to_create = CryptAuthKeyCreator::CreateKeyData(status, type);
return base::nullopt;
}
DCHECK(bundle_name == CryptAuthKeyBundle::Name::kUserKeyPair);
return ProcessNewUserKeyPairInstructions(
status, type, key_registry_->GetActiveKey(bundle_name),
new_key_to_create);
}
void CryptAuthV2EnrollerImpl::OnSyncKeysFailure(NetworkRequestError error) {
FinishAttempt(SyncKeysNetworkRequestErrorToResultCode(error));
}
......
......@@ -120,17 +120,6 @@ class CryptAuthV2EnrollerImpl : public CryptAuthV2Enroller {
base::flat_map<CryptAuthKeyBundle::Name, cryptauthv2::KeyDirective>*
new_key_directives);
// A function to help ProcessSingleKeyResponse() handle the key-creation
// instructions.
base::Optional<CryptAuthEnrollmentResult::ResultCode>
ProcessKeyCreationInstructions(
const CryptAuthKeyBundle::Name& bundle_name,
const cryptauthv2::SyncKeysResponse::SyncSingleKeyResponse&
single_key_response,
const std::string& server_ephemeral_dh,
base::Optional<CryptAuthKeyCreator::CreateKeyData>* new_key_to_create,
base::Optional<cryptauthv2::KeyDirective>* new_key_directive);
void OnSyncKeysFailure(NetworkRequestError error);
void OnKeysCreated(
......
......@@ -75,13 +75,21 @@ const char kRandomSessionId[] = "random_session_id";
const char kOldActivePublicKey[] = "old_active_public_key";
const char kOldActivePrivateKey[] = "old_active_private_key";
// User key pair active handle must be kCryptAuthFixedUserKeyPairHandle.
const char kOldActiveAsymmetricKeyHandle[] = "old_active_handle";
const CryptAuthKey kOldActiveAsymmetricKey(kOldActivePublicKey,
kOldActivePrivateKey,
CryptAuthKey::Status::kActive,
KeyType::P256,
kCryptAuthFixedUserKeyPairHandle);
kOldActiveAsymmetricKeyHandle);
const char kOldInactivePublicKey[] = "old_inactive_public_key";
const char kOldInactivePrivateKey[] = "old_inactive_private_key";
const char kOldInactiveAsymmetricKeyHandle[] = "old_inactive_handle";
const CryptAuthKey kOldInactiveAsymmetricKey(kOldInactivePublicKey,
kOldInactivePrivateKey,
CryptAuthKey::Status::kInactive,
KeyType::P256,
kOldInactiveAsymmetricKeyHandle);
const char kOldActiveSymmetricKeyMaterial[] = "old_active_symmetric_key";
const char kOldActiveSymmetricKeyHandle[] = "old_active_symmetric_key_handle";
......@@ -100,6 +108,7 @@ CryptAuthKey kOldInactiveSymmetricKey(kOldInactiveSymmetricKeyMaterial,
const char kNewPublicKey[] = "new_public_key";
const char kNewPrivateKey[] = "new_private_key";
const char kFixedUserKeyPairHandle[] = "device_key";
const char kNewSymmetricKey[] = "new_symmetric_key";
const char kNewSymmetricKeyHandle[] = "new_symmetric_key_handle";
......@@ -495,26 +504,8 @@ class DeviceSyncCryptAuthV2EnrollerImplTest
EXPECT_EQ(key.status(), create_key_data.status);
EXPECT_EQ(key.type(), create_key_data.type);
// Special handling for user key pair.
if (bundle_name == CryptAuthKeyBundle::Name::kUserKeyPair) {
if (bundle_name == CryptAuthKeyBundle::Name::kUserKeyPair)
EXPECT_EQ(key.handle(), create_key_data.handle);
const CryptAuthKey* current_active_user_key_pair =
key_registry()->GetActiveKey(
CryptAuthKeyBundle::Name::kUserKeyPair);
if (current_active_user_key_pair) {
EXPECT_EQ(key.public_key(), create_key_data.public_key);
EXPECT_EQ(current_active_user_key_pair->public_key(),
create_key_data.public_key);
EXPECT_EQ(key.private_key(), create_key_data.private_key);
EXPECT_EQ(current_active_user_key_pair->private_key(),
create_key_data.private_key);
EXPECT_EQ(KeyType::P256, create_key_data.type);
EXPECT_EQ(CryptAuthKey::Status::kActive, create_key_data.status);
}
}
}
ASSERT_TRUE(key_creator()->server_ephemeral_dh()->IsAsymmetricKey());
......@@ -523,29 +514,6 @@ class DeviceSyncCryptAuthV2EnrollerImplTest
EXPECT_EQ(KeyType::P256, key_creator()->server_ephemeral_dh()->type());
}
void VerifyEnrollSingleKeyRequest(const CryptAuthKeyBundle::Name& bundle_name,
const CryptAuthKey& new_key) {
const EnrollSingleKeyRequest& single_request_user_key_pair =
enroll_keys_request()->enroll_single_key_requests(
GetKeyBundleIndex(bundle_name));
EXPECT_EQ(CryptAuthKeyBundle::KeyBundleNameEnumToString(bundle_name),
single_request_user_key_pair.key_name());
EXPECT_EQ(new_key.handle(), single_request_user_key_pair.new_key_handle());
// No private or symmetric keys should be sent to CryptAuth, so key_material
// should only ever be populated with a public key.
EXPECT_EQ(new_key.IsAsymmetricKey() ? new_key.public_key() : std::string(),
single_request_user_key_pair.key_material());
EXPECT_EQ(CryptAuthKeyProofComputerImpl::Factory::Get()
->BuildInstance()
->ComputeKeyProof(new_key, kRandomSessionId,
kCryptAuthKeyProofSalt),
single_request_user_key_pair.key_proof());
}
CryptAuthV2Enroller* enroller() { return enroller_.get(); }
CryptAuthKeyRegistry* key_registry() { return key_registry_.get(); }
......@@ -609,6 +577,8 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest, SuccessfulEnrollment) {
// Seed key registry.
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
kOldActiveAsymmetricKey);
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
kOldInactiveAsymmetricKey);
key_registry()->SetKeyDirective(CryptAuthKeyBundle::Name::kUserKeyPair,
GetSampleOldKeyDirective());
CryptAuthKeyBundle expected_key_bundle_user_key_pair(
......@@ -631,27 +601,29 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest, SuccessfulEnrollment) {
ClientDirective expected_new_client_directive = GetSampleNewClientDirective();
KeyDirective expected_new_key_directive = GetSampleNewKeyDirective();
// For kUserKeyPair (special case):
// - active --> temporarily active during key creation
// - new --> same handle so overwrites active key with same material
// For kMasterLegacyKey:
// For kUserKeyPair:
// - active --> deleted
// - inactive --> temporarily active during key creation
// - new --> active after created
// For kMasterLegacyKey:
// - active --> active
// - inactive --> inactive
// - new --> inactive
std::vector<SyncSingleKeyResponseData> sync_single_key_responses_data = {
SyncSingleKeyResponseData(
CryptAuthKeyBundle::Name::kUserKeyPair, key_registry(),
{{kCryptAuthFixedUserKeyPairHandle,
{{kOldActiveAsymmetricKeyHandle, SyncSingleKeyResponse::DELETE},
{kOldInactiveAsymmetricKeyHandle,
SyncSingleKeyResponse::ACTIVATE}} /* handle_to_action_map */,
SyncSingleKeyResponse::ACTIVE /* new_key_creation */,
KeyType::P256 /* new_key_type */,
expected_new_key_directive /* new_key_directive */),
SyncSingleKeyResponseData(
CryptAuthKeyBundle::Name::kLegacyMasterKey, key_registry(),
{{kOldActiveSymmetricKeyHandle, SyncSingleKeyResponse::DELETE},
{{kOldActiveSymmetricKeyHandle, SyncSingleKeyResponse::ACTIVATE},
{kOldInactiveSymmetricKeyHandle,
SyncSingleKeyResponse::ACTIVATE}} /* handle_to_action_map */,
SyncSingleKeyResponse::ACTIVE /* new_key_creation */,
SyncSingleKeyResponse::DEACTIVATE}} /* handle_to_action_map */,
SyncSingleKeyResponse::INACTIVE /* new_key_creation */,
KeyType::RAW256 /* new_key_type */,
expected_new_key_directive /* new_key_directive */)};
......@@ -663,30 +635,25 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest, SuccessfulEnrollment) {
SendSyncKeysResponse(sync_keys_response);
// Verify that the key actions were applied. (Note: New keys not created yet.)
// No key actions expected for kUserKeyPair.
expected_key_bundle_user_key_pair.DeleteKey(kOldActiveAsymmetricKeyHandle);
expected_key_bundle_user_key_pair.SetActiveKey(
kOldInactiveAsymmetricKeyHandle);
EXPECT_EQ(
expected_key_bundle_user_key_pair,
*key_registry()->GetKeyBundle(CryptAuthKeyBundle::Name::kUserKeyPair));
// In kLegacyMasterKey bundle, former active key should have been deleted and
// former inactive key should now be active.
expected_key_bundle_legacy_master_key.DeleteKey(kOldActiveSymmetricKeyHandle);
expected_key_bundle_legacy_master_key.SetActiveKey(
kOldInactiveSymmetricKeyHandle);
EXPECT_EQ(expected_key_bundle_legacy_master_key,
*key_registry()->GetKeyBundle(
CryptAuthKeyBundle::Name::kLegacyMasterKey));
// Verify the key creation data, and assume successful key creation.
// Note: Since an active user key pair already exists, the same key material
// should re-used.
base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey> expected_new_keys = {
{CryptAuthKeyBundle::Name::kUserKeyPair,
CryptAuthKey(kOldActivePublicKey, kOldActivePrivateKey,
CryptAuthKey(kNewPublicKey, kNewPrivateKey,
CryptAuthKey::Status::kActive, KeyType::P256,
kCryptAuthFixedUserKeyPairHandle)},
kFixedUserKeyPairHandle)},
{CryptAuthKeyBundle::Name::kLegacyMasterKey,
CryptAuthKey(kNewSymmetricKey, CryptAuthKey::Status::kActive,
CryptAuthKey(kNewSymmetricKey, CryptAuthKey::Status::kInactive,
KeyType::RAW256, kNewSymmetricKeyHandle)}};
VerifyKeyCreatorInputs(
......@@ -699,13 +666,40 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest, SuccessfulEnrollment) {
EXPECT_EQ(kRandomSessionId, enroll_keys_request()->random_session_id());
EXPECT_EQ(kClientDhPublicKey, enroll_keys_request()->client_ephemeral_dh());
EXPECT_EQ(2, enroll_keys_request()->enroll_single_key_requests_size());
VerifyEnrollSingleKeyRequest(
CryptAuthKeyBundle::Name::kUserKeyPair,
expected_new_keys.find(CryptAuthKeyBundle::Name::kUserKeyPair)->second);
VerifyEnrollSingleKeyRequest(
CryptAuthKeyBundle::Name::kLegacyMasterKey,
expected_new_keys.find(CryptAuthKeyBundle::Name::kLegacyMasterKey)
->second);
std::unique_ptr<CryptAuthKeyProofComputer> key_proof_computer =
CryptAuthKeyProofComputerImpl::Factory::Get()->BuildInstance();
const EnrollSingleKeyRequest& single_request_user_key_pair =
enroll_keys_request()->enroll_single_key_requests(
GetKeyBundleIndex(CryptAuthKeyBundle::Name::kUserKeyPair));
EXPECT_EQ(CryptAuthKeyBundle::KeyBundleNameEnumToString(
CryptAuthKeyBundle::Name::kUserKeyPair),
single_request_user_key_pair.key_name());
EXPECT_EQ(kFixedUserKeyPairHandle,
single_request_user_key_pair.new_key_handle());
EXPECT_EQ(kNewPublicKey, single_request_user_key_pair.key_material());
EXPECT_EQ(key_proof_computer->ComputeKeyProof(
expected_new_keys.find(CryptAuthKeyBundle::Name::kUserKeyPair)
->second,
kRandomSessionId, kCryptAuthKeyProofSalt),
single_request_user_key_pair.key_proof());
const EnrollSingleKeyRequest& single_request_legacy_master_key =
enroll_keys_request()->enroll_single_key_requests(
GetKeyBundleIndex(CryptAuthKeyBundle::Name::kLegacyMasterKey));
EXPECT_EQ(CryptAuthKeyBundle::KeyBundleNameEnumToString(
CryptAuthKeyBundle::Name::kLegacyMasterKey),
single_request_legacy_master_key.key_name());
EXPECT_EQ(kNewSymmetricKeyHandle,
single_request_legacy_master_key.new_key_handle());
EXPECT_TRUE(single_request_legacy_master_key.key_material().empty());
EXPECT_EQ(
key_proof_computer->ComputeKeyProof(
expected_new_keys.find(CryptAuthKeyBundle::Name::kLegacyMasterKey)
->second,
kRandomSessionId, kCryptAuthKeyProofSalt),
single_request_legacy_master_key.key_proof());
// Assume a successful EnrollKeys() call.
// Note: No parameters in EnrollKeysResponse are processed by the enroller
......@@ -737,71 +731,16 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest, SuccessfulEnrollment) {
*key_registry()->GetKeyBundle(bundle_name));
}
TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest,
SuccessfulEnrollment_CreateUserKeyPair_NoKeyInRegistry) {
CallEnroll(GetSampleClientMetadata(), GetSampleClientAppMetadata(),
GetSamplePreviousClientDirectivePolicyReference());
ClientDirective expected_new_client_directive = GetSampleNewClientDirective();
KeyDirective expected_new_key_directive = GetSampleNewKeyDirective();
SyncKeysResponse sync_keys_response = BuildSyncKeysResponse(
{SyncSingleKeyResponseData(
CryptAuthKeyBundle::Name::kUserKeyPair, key_registry(),
{} /* handle_to_action_map */,
SyncSingleKeyResponse::ACTIVE /* new_key_creation */,
KeyType::P256 /* new_key_type */,
expected_new_key_directive /* new_key_directive */)},
kRandomSessionId, kServerEphemeralDh, expected_new_client_directive);
SendSyncKeysResponse(sync_keys_response);
// Note: Because there is not an existing kUserKeyPair key in registry, a new
// key should be generated. (If there was an existing key, its key material
// would be reused because the kUserKeyPair key should not be rotated.)
base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey> expected_new_keys = {
{CryptAuthKeyBundle::Name::kUserKeyPair,
CryptAuthKey(kNewPublicKey, kNewPrivateKey,
CryptAuthKey::Status::kActive, KeyType::P256,
kCryptAuthFixedUserKeyPairHandle)}};
VerifyKeyCreatorInputs(
expected_new_keys,
kServerEphemeralDh /* expected_server_ephemeral_dh_public_key */);
RunKeyCreator(expected_new_keys, kClientEphemeralDh);
EXPECT_EQ(1, enroll_keys_request()->enroll_single_key_requests_size());
VerifyEnrollSingleKeyRequest(
CryptAuthKeyBundle::Name::kUserKeyPair,
expected_new_keys.find(CryptAuthKeyBundle::Name::kUserKeyPair)->second);
SendEnrollKeysResponse(EnrollKeysResponse());
EXPECT_EQ(CryptAuthEnrollmentResult(
CryptAuthEnrollmentResult::ResultCode::kSuccessNewKeysEnrolled,
expected_new_client_directive),
enrollment_result());
CryptAuthKeyBundle expected_key_bundle(
CryptAuthKeyBundle::Name::kUserKeyPair);
expected_key_bundle.AddKey(
expected_new_keys.find(CryptAuthKeyBundle::Name::kUserKeyPair)->second);
expected_key_bundle.set_key_directive(expected_new_key_directive);
EXPECT_EQ(expected_key_bundle, *key_registry()->GetKeyBundle(
CryptAuthKeyBundle::Name::kUserKeyPair));
}
TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest,
SuccessfulEnrollment_NoKeysCreated) {
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kLegacyMasterKey,
kOldActiveSymmetricKey);
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kLegacyMasterKey,
kOldInactiveSymmetricKey);
key_registry()->SetKeyDirective(CryptAuthKeyBundle::Name::kLegacyMasterKey,
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
kOldActiveAsymmetricKey);
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
kOldInactiveAsymmetricKey);
key_registry()->SetKeyDirective(CryptAuthKeyBundle::Name::kUserKeyPair,
GetSampleOldKeyDirective());
CryptAuthKeyBundle expected_key_bundle(*key_registry()->GetKeyBundle(
CryptAuthKeyBundle::Name::kLegacyMasterKey));
CryptAuthKeyBundle expected_key_bundle(
*key_registry()->GetKeyBundle(CryptAuthKeyBundle::Name::kUserKeyPair));
CallEnroll(GetSampleClientMetadata(), GetSampleClientAppMetadata(),
GetSamplePreviousClientDirectivePolicyReference());
......@@ -810,19 +749,18 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest,
// but not create any new keys.
SyncKeysResponse sync_keys_response =
BuildSyncKeysResponse({SyncSingleKeyResponseData(
CryptAuthKeyBundle::Name::kLegacyMasterKey, key_registry(),
{{kOldActiveSymmetricKeyHandle, SyncSingleKeyResponse::DEACTIVATE},
{kOldInactiveSymmetricKeyHandle,
CryptAuthKeyBundle::Name::kUserKeyPair, key_registry(),
{{kOldActiveAsymmetricKeyHandle, SyncSingleKeyResponse::DEACTIVATE},
{kOldInactiveAsymmetricKeyHandle,
SyncSingleKeyResponse::ACTIVATE}} /* handle_to_action_map */,
SyncSingleKeyResponse::NONE /* new_key_creation */,
base::nullopt /* new_key_type */,
base::nullopt /* new_key_directive */)});
SendSyncKeysResponse(sync_keys_response);
expected_key_bundle.SetActiveKey(kOldInactiveSymmetricKeyHandle);
EXPECT_EQ(expected_key_bundle,
*key_registry()->GetKeyBundle(
CryptAuthKeyBundle::Name::kLegacyMasterKey));
expected_key_bundle.SetActiveKey(kOldInactiveAsymmetricKeyHandle);
EXPECT_EQ(expected_key_bundle, *key_registry()->GetKeyBundle(
CryptAuthKeyBundle::Name::kUserKeyPair));
EXPECT_EQ(CryptAuthEnrollmentResult(
CryptAuthEnrollmentResult::ResultCode::kSuccessNoNewKeysNeeded,
......@@ -915,7 +853,7 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest, Failure_InvalidKeyActions_Size) {
TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest,
Failure_InvalidKeyActions_NoActiveKey) {
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kLegacyMasterKey,
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
kOldActiveAsymmetricKey);
CallEnroll(GetSampleClientMetadata(), GetSampleClientAppMetadata(),
......@@ -924,8 +862,8 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest,
// Try to deactivate the only active key.
SyncKeysResponse sync_keys_response =
BuildSyncKeysResponse({SyncSingleKeyResponseData(
CryptAuthKeyBundle::Name::kLegacyMasterKey, key_registry(),
{{kOldActiveSymmetricKeyHandle,
CryptAuthKeyBundle::Name::kUserKeyPair, key_registry(),
{{kOldActiveAsymmetricKeyHandle,
SyncSingleKeyResponse::DEACTIVATE}} /* handle_to_action_map */,
SyncSingleKeyResponse::NONE /* new_key_creation */,
base::nullopt /* new_key_type */,
......@@ -960,52 +898,6 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest,
enrollment_result());
}
TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest,
Failure_InvalidKeyCreationInstructions_UnsupportedUserKeyPairKeyType) {
CallEnroll(GetSampleClientMetadata(), GetSampleClientAppMetadata(),
GetSamplePreviousClientDirectivePolicyReference());
// Instruct client to create a symmetric user key pair. The user key pair is
// heavily protected against anything other than P256.
SyncKeysResponse sync_keys_response =
BuildSyncKeysResponse({SyncSingleKeyResponseData(
CryptAuthKeyBundle::Name::kUserKeyPair, key_registry(),
{} /* handle_to_action_map */,
SyncSingleKeyResponse::ACTIVE /* new_key_creation */,
KeyType::RAW256 /* new_key_type */,
base::nullopt /* new_key_directive */)});
SendSyncKeysResponse(sync_keys_response);
EXPECT_EQ(CryptAuthEnrollmentResult(
CryptAuthEnrollmentResult::ResultCode::
kErrorUserKeyPairCreationInstructionsInvalid,
sync_keys_response.client_directive()),
enrollment_result());
}
TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest,
Failure_InvalidKeyCreationInstructions_NewUserKeyPairMustBeActive) {
CallEnroll(GetSampleClientMetadata(), GetSampleClientAppMetadata(),
GetSamplePreviousClientDirectivePolicyReference());
// Instruct client to create a new, inactive user key pair. Since there can
// only be one user key pair in the bundle, a new one must be active.
SyncKeysResponse sync_keys_response =
BuildSyncKeysResponse({SyncSingleKeyResponseData(
CryptAuthKeyBundle::Name::kUserKeyPair, key_registry(),
{} /* handle_to_action_map */,
SyncSingleKeyResponse::INACTIVE /* new_key_creation */,
KeyType::P256 /* new_key_type */,
base::nullopt /* new_key_directive */)});
SendSyncKeysResponse(sync_keys_response);
EXPECT_EQ(CryptAuthEnrollmentResult(
CryptAuthEnrollmentResult::ResultCode::
kErrorUserKeyPairCreationInstructionsInvalid,
sync_keys_response.client_directive()),
enrollment_result());
}
TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest,
Failure_InvalidKeyCreationInstructions_NoServerDiffieHellman) {
CallEnroll(GetSampleClientMetadata(), GetSampleClientAppMetadata(),
......@@ -1013,7 +905,7 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest,
SyncKeysResponse sync_keys_response =
BuildSyncKeysResponse({SyncSingleKeyResponseData(
CryptAuthKeyBundle::Name::kLegacyMasterKey, key_registry(),
CryptAuthKeyBundle::Name::kUserKeyPair, key_registry(),
{} /* handle_to_action_map */,
SyncSingleKeyResponse::ACTIVE /* new_key_creation */,
KeyType::RAW256 /* new_key_type */,
......@@ -1049,7 +941,7 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest,
{CryptAuthKeyBundle::Name::kUserKeyPair,
CryptAuthKey(kNewPublicKey, kNewPrivateKey,
CryptAuthKey::Status::kActive, KeyType::P256,
kCryptAuthFixedUserKeyPairHandle)}};
kFixedUserKeyPairHandle)}};
RunKeyCreator(expected_new_keys, kClientEphemeralDh);
EXPECT_EQ(CryptAuthEnrollmentResult(CryptAuthEnrollmentResult::ResultCode::
......@@ -1088,7 +980,7 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest, Failure_EnrollKeysApiCall) {
{CryptAuthKeyBundle::Name::kUserKeyPair,
CryptAuthKey(kNewPublicKey, kNewPrivateKey,
CryptAuthKey::Status::kActive, KeyType::P256,
kCryptAuthFixedUserKeyPairHandle)}};
kFixedUserKeyPairHandle)}};
RunKeyCreator(expected_new_keys, kClientEphemeralDh);
FailEnrollKeysRequest(NetworkRequestError::kBadRequest);
......@@ -1157,7 +1049,7 @@ TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest,
{CryptAuthKeyBundle::Name::kUserKeyPair,
CryptAuthKey(kNewPublicKey, kNewPrivateKey,
CryptAuthKey::Status::kActive, KeyType::P256,
kCryptAuthFixedUserKeyPairHandle)}};
kFixedUserKeyPairHandle)}};
RunKeyCreator(expected_new_keys, kClientEphemeralDh);
// Timeout waiting for EnrollKeysResponse.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment