1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ASH_ATTESTATION_TPM_CHALLENGE_KEY_H_
#define CHROME_BROWSER_ASH_ATTESTATION_TPM_CHALLENGE_KEY_H_
#include <memory>
#include <optional>
#include <string>
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "chrome/browser/ash/attestation/tpm_challenge_key_result.h"
#include "chrome/browser/ash/attestation/tpm_challenge_key_subtle.h"
#include "chromeos/ash/components/dbus/attestation/attestation_ca.pb.h"
#include "chromeos/ash/components/dbus/attestation/keystore.pb.h"
#include "chromeos/ash/components/dbus/constants/attestation_constants.h"
class Profile;
class AttestationFlow;
namespace ash {
namespace attestation {
// Prefix for naming machine keys used for SignedPublicKeyAndChallenge when
// challenging the EMK with register=true.
inline constexpr char kEnterpriseMachineKeyForSpkacPrefix[] =
"attest-ent-machine-";
//========================= TpmChallengeKeyFactory =============================
class TpmChallengeKey;
class TpmChallengeKeyFactory final {
public:
static std::unique_ptr<TpmChallengeKey> Create();
static void SetForTesting(std::unique_ptr<TpmChallengeKey> next_result);
private:
static TpmChallengeKey* next_result_for_testing_;
};
//=========================== TpmChallengeKey ==================================
// Asynchronously runs the flow to challenge a key in the caller context. This
// is a wrapper around TpmChallengeKeySubtle with an easier-to-use interface.
// TpmChallengeKeySubtle can be used directly to get more control over main
// steps to build the response.
class TpmChallengeKey {
public:
TpmChallengeKey(const TpmChallengeKey&) = delete;
TpmChallengeKey& operator=(const TpmChallengeKey&) = delete;
virtual ~TpmChallengeKey() = default;
// Should be called only once for every instance. |TpmChallengeKey| object
// should live as long as response from |BuildResponse| function via
// |callback| is expected. On destruction it stops challenge process and
// silently discards callback.
// The response consists of up to two parts: 1) a response to the challenge
// and optionally 2) an SPKAC. They can be generated using different keys:
// A) ENTERPRISE_MACHINE && !register_key
// => 1) Stable device key + 2) Empty
// B) ENTERPRISE_MACHINE && register_key
// => 1) Stable device key + 2) Key(key_name)
// C) ENTERPRISE_USER && !register_key
// => 1) Key(key_name) + 2) Empty
// D) ENTERPRISE_USER && register_key
// => 1) Key(key_name) + 2) Key(key_name)
// E) DEVICE_TRUST_CONNECTOR && !register_key
// => 1) Key(key_name) + 2) Empty
// In case B) |key_name| cannot be empty. In case C), D) some default name
// will be used if |key_name| is empty.
// When using DEVICE_TRUST_CONNECTOR, `register_key` is not supported and
// `key_name` cannot be empty.
// The response can also contain |signals| which consist of a set of
// information about the device that is given to the IdP after the challenge
// response has been verified. These signals can be used as input to an AuthN
// decision. Signals are collected in a dictionary and are JSON stringified.
// The signals are optional since they can be null when no signals are set on
// the response, empty when no signals were collected (i.e empty signals
// dictionary), or non empty. More information on signals collection can be
// found in the |SignalsService|.
virtual void BuildResponse(::attestation::VerifiedAccessFlow flow_type,
Profile* profile,
TpmChallengeKeyCallback callback,
const std::string& challenge,
bool register_key,
::attestation::KeyType key_crypto_type,
const std::string& key_name,
const std::optional<std::string>& signals) = 0;
protected:
// Use TpmChallengeKeyFactory for creation.
TpmChallengeKey() = default;
};
//=========================== TpmChallengeKeyImpl ==============================
class TpmChallengeKeyImpl final : public TpmChallengeKey {
public:
// Use TpmChallengeKeyFactory for creation.
TpmChallengeKeyImpl();
// Use only for testing.
explicit TpmChallengeKeyImpl(
AttestationFlow* attestation_flow_for_testing,
MachineCertificateUploader* certificate_uploader_for_testing);
TpmChallengeKeyImpl(const TpmChallengeKeyImpl&) = delete;
TpmChallengeKeyImpl& operator=(const TpmChallengeKeyImpl&) = delete;
~TpmChallengeKeyImpl() override;
// TpmChallengeKey
void BuildResponse(::attestation::VerifiedAccessFlow flow_type,
Profile* profile,
TpmChallengeKeyCallback callback,
const std::string& challenge,
bool register_key,
::attestation::KeyType key_crypto_type,
const std::string& key_name,
const std::optional<std::string>& signals) override;
private:
void OnPrepareKeyDone(const TpmChallengeKeyResult& prepare_key_result);
void OnSignChallengeDone(const TpmChallengeKeyResult& sign_challenge_result);
void OnRegisterKeyDone(const TpmChallengeKeyResult& challenge_response,
const TpmChallengeKeyResult& register_key_result);
bool register_key_ = false;
std::string challenge_;
TpmChallengeKeyResult challenge_response_;
TpmChallengeKeyCallback callback_;
std::unique_ptr<TpmChallengeKeySubtle> tpm_challenge_key_subtle_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<TpmChallengeKeyImpl> weak_factory_{this};
};
} // namespace attestation
} // namespace ash
#endif // CHROME_BROWSER_ASH_ATTESTATION_TPM_CHALLENGE_KEY_H_
|