File: attestation_flow_adaptive.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (171 lines) | stat: -rw-r--r-- 6,953 bytes parent folder | download | duplicates (7)
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/ash/components/attestation/attestation_flow_adaptive.h"

#include <memory>
#include <optional>
#include <utility>

#include "base/logging.h"
#include "chromeos/ash/components/attestation/attestation_flow.h"
#include "chromeos/ash/components/dbus/constants/attestation_constants.h"

namespace ash {
namespace attestation {

struct AttestationFlowAdaptive::GetCertificateParams {
  AttestationCertificateProfile certificate_profile;
  AccountId account_id;
  std::string request_origin;
  bool force_new_key;
  ::attestation::KeyType key_crypto_type;
  std::string key_name;
  std::optional<AttestationFlow::CertProfileSpecificData> profile_specific_data;
};

// Consructs the object with `AttestationFlowTypeDecider` and
// `AttestationFlowFactory`
AttestationFlowAdaptive::AttestationFlowAdaptive(
    std::unique_ptr<ServerProxy> server_proxy)
    : AttestationFlowAdaptive(std::move(server_proxy),
                              std::make_unique<AttestationFlowTypeDecider>(),
                              std::make_unique<AttestationFlowFactory>()) {}

// We don't really use the parent class to perform attestation flow. Just give
// it a null `ServerProxy`.
AttestationFlowAdaptive::AttestationFlowAdaptive(
    std::unique_ptr<ServerProxy> server_proxy,
    std::unique_ptr<AttestationFlowTypeDecider> type_decider,
    std::unique_ptr<AttestationFlowFactory> factory)
    : server_proxy_(std::move(server_proxy)),
      raw_server_proxy_(server_proxy_.get()),
      attestation_flow_type_decider_(std::move(type_decider)),
      attestation_flow_factory_(std::move(factory)) {}

AttestationFlowAdaptive::~AttestationFlowAdaptive() = default;

void AttestationFlowAdaptive::GetCertificate(
    AttestationCertificateProfile certificate_profile,
    const AccountId& account_id,
    const std::string& request_origin,
    bool force_new_key,
    ::attestation::KeyType key_crypto_type,
    const std::string& key_name,
    const std::optional<AttestationFlow::CertProfileSpecificData>&
        profile_specific_data,
    CertificateCallback callback) {
  GetCertificateParams params = {
      /*.certificate_profile=*/certificate_profile,
      /*.account_id=*/account_id,
      /*.request_origin=*/request_origin,
      /*.force_new_key=*/force_new_key,
      /*.key_crypto_type=*/key_crypto_type,
      /*.key_name=*/key_name,
      /*.profile_specific_data=*/profile_specific_data,
  };

  auto status_reporter = std::make_unique<AttestationFlowStatusReporter>();
  auto* raw_status_reporter = status_reporter.get();

  // Start the flow with checking if platform-side integrated attestation is an
  // valid option.
  attestation_flow_type_decider_->CheckType(
      raw_server_proxy_, raw_status_reporter,
      base::BindOnce(&AttestationFlowAdaptive::OnCheckAttestationFlowType,
                     weak_factory_.GetWeakPtr(), std::move(params),
                     std::move(status_reporter), std::move(callback)));
}

void AttestationFlowAdaptive::OnCheckAttestationFlowType(
    const GetCertificateParams& params,
    std::unique_ptr<AttestationFlowStatusReporter> status_reporter,
    CertificateCallback callback,
    bool is_integrated_flow_possible) {
  LOG_IF(WARNING, !is_integrated_flow_possible)
      << "Skipping the integrated attestation flow.";
  StartGetCertificate(params, std::move(status_reporter), std::move(callback),
                      is_integrated_flow_possible);
}

void AttestationFlowAdaptive::StartGetCertificate(
    const GetCertificateParams& params,
    std::unique_ptr<AttestationFlowStatusReporter> status_reporter,
    CertificateCallback callback,
    bool is_default_flow_valid) {
  InitializeAttestationFlowFactory();

  // Use the fallback if the inetgrated flow is not valid.
  if (!is_default_flow_valid) {
    AttestationFlow* fallback_attestation_flow =
        attestation_flow_factory_->GetFallback();
    fallback_attestation_flow->GetCertificate(
        /*certificate_profile=*/params.certificate_profile,
        /*account_id=*/params.account_id,
        /*request_origin=*/params.request_origin,
        /*force_new_key=*/params.force_new_key,
        /*key_crypto_type=*/params.key_crypto_type,
        /*key_name=*/params.key_name,
        /*profile_specific_data=*/params.profile_specific_data,
        /*callback=*/
        base::BindOnce(
            &AttestationFlowAdaptive::OnGetCertificateWithFallbackFlow,
            weak_factory_.GetWeakPtr(), std::move(status_reporter),
            std::move(callback)));
    return;
  }
  AttestationFlow* default_attestation_flow =
      attestation_flow_factory_->GetDefault();
  default_attestation_flow->GetCertificate(
      /*certificate_profile=*/params.certificate_profile,
      /*account_id=*/params.account_id,
      /*request_origin=*/params.request_origin,
      /*force_new_key=*/params.force_new_key,
      /*key_crypto_type=*/params.key_crypto_type, /*key_name=*/params.key_name,
      /*profile_specific_data=*/params.profile_specific_data,
      /*callback=*/
      base::BindOnce(&AttestationFlowAdaptive::OnGetCertificateWithDefaultFlow,
                     weak_factory_.GetWeakPtr(), params,
                     std::move(status_reporter), std::move(callback)));
}

void AttestationFlowAdaptive::InitializeAttestationFlowFactory() {
  if (!is_attestation_flow_initialized_) {
    is_attestation_flow_initialized_ = true;
    // At this point, we have confirmed if the default (platform-side) flow is a
    // valid option. Now hand over the ownership of `server_proxy_`.`
    attestation_flow_factory_->Initialize(std::move(server_proxy_));
  }
}

void AttestationFlowAdaptive::OnGetCertificateWithDefaultFlow(
    const GetCertificateParams& params,
    std::unique_ptr<AttestationFlowStatusReporter> status_reporter,
    CertificateCallback callback,
    AttestationStatus status,
    const std::string& pem_certificate_chain) {
  status_reporter->OnDefaultFlowStatus(/*success=*/status ==
                                       ATTESTATION_SUCCESS);
  if (status == ATTESTATION_SUCCESS) {
    std::move(callback).Run(status, pem_certificate_chain);
    return;
  }

  LOG(WARNING) << "Default attestation flow failed: " << status;
  StartGetCertificate(params, std::move(status_reporter), std::move(callback),
                      /*is_default_flow_valid=*/false);
}

void AttestationFlowAdaptive::OnGetCertificateWithFallbackFlow(
    std::unique_ptr<AttestationFlowStatusReporter> status_reporter,
    CertificateCallback callback,
    AttestationStatus status,
    const std::string& pem_certificate_chain) {
  status_reporter->OnFallbackFlowStatus(/*success=*/status ==
                                        ATTESTATION_SUCCESS);
  std::move(callback).Run(status, pem_certificate_chain);
}

}  // namespace attestation
}  // namespace ash