OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/attestation/attestation_flow.h" | 5 #include "chromeos/attestation/attestation_flow.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "chromeos/cryptohome/async_method_caller.h" | 8 #include "chromeos/cryptohome/async_method_caller.h" |
9 #include "chromeos/dbus/cryptohome_client.h" | 9 #include "chromeos/dbus/cryptohome_client.h" |
10 | 10 |
(...skipping 20 matching lines...) Expand all Loading... |
31 LOG(ERROR) << "Attestation: Failed to query enrollment state."; | 31 LOG(ERROR) << "Attestation: Failed to query enrollment state."; |
32 if (!on_fail.is_null()) | 32 if (!on_fail.is_null()) |
33 on_fail.Run(); | 33 on_fail.Run(); |
34 return; | 34 return; |
35 } | 35 } |
36 const base::Closure& task = value ? on_true : on_false; | 36 const base::Closure& task = value ? on_true : on_false; |
37 if (!task.is_null()) | 37 if (!task.is_null()) |
38 task.Run(); | 38 task.Run(); |
39 } | 39 } |
40 | 40 |
| 41 void DBusDataMethodCallback( |
| 42 const AttestationFlow::CertificateCallback& callback, |
| 43 DBusMethodCallStatus status, |
| 44 bool result, |
| 45 const std::string& data) { |
| 46 if (status != DBUS_METHOD_CALL_SUCCESS) { |
| 47 LOG(ERROR) << "Attestation: DBus data operation failed."; |
| 48 if (!callback.is_null()) |
| 49 callback.Run(false, ""); |
| 50 return; |
| 51 } |
| 52 if (!callback.is_null()) |
| 53 callback.Run(result, data); |
| 54 } |
| 55 |
| 56 AttestationKeyType GetKeyTypeForProfile( |
| 57 AttestationCertificateProfile profile) { |
| 58 switch (profile) { |
| 59 case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE: |
| 60 return KEY_DEVICE; |
| 61 case PROFILE_ENTERPRISE_USER_CERTIFICATE: |
| 62 return KEY_USER; |
| 63 } |
| 64 NOTREACHED(); |
| 65 return KEY_USER; |
| 66 } |
| 67 |
| 68 std::string GetKeyNameForProfile( |
| 69 AttestationCertificateProfile profile) { |
| 70 switch (profile) { |
| 71 case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE: |
| 72 return kEnterpriseMachineKey; |
| 73 case PROFILE_ENTERPRISE_USER_CERTIFICATE: |
| 74 return kEnterpriseUserKey; |
| 75 } |
| 76 NOTREACHED(); |
| 77 return ""; |
| 78 } |
| 79 |
| 80 int GetCertificateOptionsForProfile( |
| 81 AttestationCertificateProfile profile) { |
| 82 switch (profile) { |
| 83 case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE: |
| 84 return CERTIFICATE_INCLUDE_STABLE_ID | CERTIFICATE_INCLUDE_DEVICE_STATE; |
| 85 case PROFILE_ENTERPRISE_USER_CERTIFICATE: |
| 86 return CERTIFICATE_INCLUDE_DEVICE_STATE; |
| 87 } |
| 88 NOTREACHED(); |
| 89 return CERTIFICATE_OPTION_NONE; |
| 90 } |
| 91 |
41 } // namespace | 92 } // namespace |
42 | 93 |
43 const char AttestationFlow::kEnterpriseMachineKey[] = "attest-ent-machine"; | |
44 | |
45 AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller* async_caller, | 94 AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller* async_caller, |
46 CryptohomeClient* cryptohome_client, | 95 CryptohomeClient* cryptohome_client, |
47 scoped_ptr<ServerProxy> server_proxy) | 96 scoped_ptr<ServerProxy> server_proxy) |
48 : weak_factory_(this), | 97 : async_caller_(async_caller), |
49 async_caller_(async_caller), | |
50 cryptohome_client_(cryptohome_client), | 98 cryptohome_client_(cryptohome_client), |
51 server_proxy_(server_proxy.Pass()) { | 99 server_proxy_(server_proxy.Pass()), |
| 100 weak_factory_(this) { |
52 } | 101 } |
53 | 102 |
54 AttestationFlow::~AttestationFlow() { | 103 AttestationFlow::~AttestationFlow() { |
55 } | 104 } |
56 | 105 |
57 void AttestationFlow::GetCertificate(const std::string& name, | 106 void AttestationFlow::GetCertificate( |
58 const CertificateCallback& callback) { | 107 AttestationCertificateProfile certificate_profile, |
| 108 bool force_new_key, |
| 109 const CertificateCallback& callback) { |
59 // If this device has not enrolled with the Privacy CA, we need to do that | 110 // If this device has not enrolled with the Privacy CA, we need to do that |
60 // first. Once enrolled we can proceed with the certificate request. | 111 // first. Once enrolled we can proceed with the certificate request. |
61 base::Closure do_cert_request = base::Bind( | 112 base::Closure do_cert_request = base::Bind( |
62 &AttestationFlow::StartCertificateRequest, | 113 &AttestationFlow::StartCertificateRequest, |
63 weak_factory_.GetWeakPtr(), | 114 weak_factory_.GetWeakPtr(), |
64 name, | 115 certificate_profile, |
| 116 force_new_key, |
65 callback); | 117 callback); |
66 base::Closure on_enroll_failure = base::Bind(callback, false, ""); | 118 base::Closure on_enroll_failure = base::Bind(callback, false, ""); |
67 base::Closure do_enroll = base::Bind(&AttestationFlow::StartEnroll, | 119 base::Closure do_enroll = base::Bind(&AttestationFlow::StartEnroll, |
68 weak_factory_.GetWeakPtr(), | 120 weak_factory_.GetWeakPtr(), |
69 on_enroll_failure, | 121 on_enroll_failure, |
70 do_cert_request); | 122 do_cert_request); |
71 cryptohome_client_->TpmAttestationIsEnrolled(base::Bind( | 123 cryptohome_client_->TpmAttestationIsEnrolled(base::Bind( |
72 &DBusBoolRedirectCallback, | 124 &DBusBoolRedirectCallback, |
73 do_cert_request, // If enrolled, proceed with cert request. | 125 do_cert_request, // If enrolled, proceed with cert request. |
74 do_enroll, // If not enrolled, initiate enrollment. | 126 do_enroll, // If not enrolled, initiate enrollment. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 on_failure.Run(); | 188 on_failure.Run(); |
137 return; | 189 return; |
138 } | 190 } |
139 | 191 |
140 // Enrollment has successfully completed, we can move on to whatever is next. | 192 // Enrollment has successfully completed, we can move on to whatever is next. |
141 if (!next_task.is_null()) | 193 if (!next_task.is_null()) |
142 next_task.Run(); | 194 next_task.Run(); |
143 } | 195 } |
144 | 196 |
145 void AttestationFlow::StartCertificateRequest( | 197 void AttestationFlow::StartCertificateRequest( |
146 const std::string& name, | 198 AttestationCertificateProfile certificate_profile, |
| 199 bool generate_new_key, |
147 const CertificateCallback& callback) { | 200 const CertificateCallback& callback) { |
148 // Get the attestation service to create a Privacy CA certificate request. | 201 AttestationKeyType key_type = GetKeyTypeForProfile(certificate_profile); |
149 int options = CryptohomeClient::INCLUDE_DEVICE_STATE; | 202 std::string key_name = GetKeyNameForProfile(certificate_profile); |
150 if (name == kEnterpriseMachineKey) | 203 if (generate_new_key) { |
151 options |= CryptohomeClient::INCLUDE_STABLE_ID; | 204 // Get the attestation service to create a Privacy CA certificate request. |
152 async_caller_->AsyncTpmAttestationCreateCertRequest( | 205 async_caller_->AsyncTpmAttestationCreateCertRequest( |
153 options, | 206 GetCertificateOptionsForProfile(certificate_profile), |
154 base::Bind(&AttestationFlow::SendCertificateRequestToPCA, | 207 base::Bind(&AttestationFlow::SendCertificateRequestToPCA, |
155 weak_factory_.GetWeakPtr(), | 208 weak_factory_.GetWeakPtr(), |
156 name, | 209 key_type, |
157 callback)); | 210 key_name, |
| 211 callback)); |
| 212 } else { |
| 213 // If the key already exists, query the existing certificate. |
| 214 base::Closure on_key_exists = base::Bind( |
| 215 &AttestationFlow::GetExistingCertificate, |
| 216 weak_factory_.GetWeakPtr(), |
| 217 key_type, |
| 218 key_name, |
| 219 callback); |
| 220 // If the key does not exist, call this method back with |generate_new_key| |
| 221 // set to true. |
| 222 base::Closure on_key_not_exists = base::Bind( |
| 223 &AttestationFlow::StartCertificateRequest, |
| 224 weak_factory_.GetWeakPtr(), |
| 225 certificate_profile, |
| 226 true, |
| 227 callback); |
| 228 cryptohome_client_->TpmAttestationDoesKeyExist( |
| 229 key_type, |
| 230 key_name, |
| 231 base::Bind(&DBusBoolRedirectCallback, |
| 232 on_key_exists, |
| 233 on_key_not_exists, |
| 234 base::Bind(callback, false, ""))); |
| 235 } |
158 } | 236 } |
159 | 237 |
160 void AttestationFlow::SendCertificateRequestToPCA( | 238 void AttestationFlow::SendCertificateRequestToPCA( |
161 const std::string& name, | 239 AttestationKeyType key_type, |
| 240 const std::string& key_name, |
162 const CertificateCallback& callback, | 241 const CertificateCallback& callback, |
163 bool success, | 242 bool success, |
164 const std::string& data) { | 243 const std::string& data) { |
165 if (!success) { | 244 if (!success) { |
166 LOG(ERROR) << "Attestation: Failed to create certificate request."; | 245 LOG(ERROR) << "Attestation: Failed to create certificate request."; |
167 if (!callback.is_null()) | 246 if (!callback.is_null()) |
168 callback.Run(false, ""); | 247 callback.Run(false, ""); |
169 return; | 248 return; |
170 } | 249 } |
171 | 250 |
172 // Send the request to the Privacy CA. | 251 // Send the request to the Privacy CA. |
173 server_proxy_->SendCertificateRequest( | 252 server_proxy_->SendCertificateRequest( |
174 data, | 253 data, |
175 base::Bind(&AttestationFlow::SendCertificateResponseToDaemon, | 254 base::Bind(&AttestationFlow::SendCertificateResponseToDaemon, |
176 weak_factory_.GetWeakPtr(), | 255 weak_factory_.GetWeakPtr(), |
177 name, | 256 key_type, |
| 257 key_name, |
178 callback)); | 258 callback)); |
179 } | 259 } |
180 | 260 |
181 void AttestationFlow::SendCertificateResponseToDaemon( | 261 void AttestationFlow::SendCertificateResponseToDaemon( |
182 const std::string& name, | 262 AttestationKeyType key_type, |
| 263 const std::string& key_name, |
183 const CertificateCallback& callback, | 264 const CertificateCallback& callback, |
184 bool success, | 265 bool success, |
185 const std::string& data) { | 266 const std::string& data) { |
186 if (!success) { | 267 if (!success) { |
187 LOG(ERROR) << "Attestation: Certificate request failed."; | 268 LOG(ERROR) << "Attestation: Certificate request failed."; |
188 if (!callback.is_null()) | 269 if (!callback.is_null()) |
189 callback.Run(false, ""); | 270 callback.Run(false, ""); |
190 return; | 271 return; |
191 } | 272 } |
192 | 273 |
193 // Forward the response to the attestation service to complete the operation. | 274 // Forward the response to the attestation service to complete the operation. |
194 CryptohomeClient::AttestationKeyType key_type = CryptohomeClient::USER_KEY; | |
195 if (name == kEnterpriseMachineKey) | |
196 key_type = CryptohomeClient::DEVICE_KEY; | |
197 async_caller_->AsyncTpmAttestationFinishCertRequest(data, | 275 async_caller_->AsyncTpmAttestationFinishCertRequest(data, |
198 key_type, | 276 key_type, |
199 name, | 277 key_name, |
200 base::Bind(callback)); | 278 base::Bind(callback)); |
201 } | 279 } |
202 | 280 |
| 281 void AttestationFlow::GetExistingCertificate( |
| 282 AttestationKeyType key_type, |
| 283 const std::string& key_name, |
| 284 const CertificateCallback& callback) { |
| 285 cryptohome_client_->TpmAttestationGetCertificate( |
| 286 key_type, |
| 287 key_name, |
| 288 base::Bind(&DBusDataMethodCallback, callback)); |
| 289 } |
| 290 |
203 } // namespace attestation | 291 } // namespace attestation |
204 } // namespace chromeos | 292 } // namespace chromeos |
OLD | NEW |