1 //
2 // Copyright (C) 2015 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "attestation/server/attestation_service.h"
18
19 #include <string>
20
21 #include <base/callback.h>
22 #include <brillo/bind_lambda.h>
23 #include <brillo/data_encoding.h>
24 #include <brillo/http/http_utils.h>
25 #include <brillo/mime_utils.h>
26 #include <crypto/sha2.h>
27
28 #include "attestation/common/attestation_ca.pb.h"
29 #include "attestation/common/database.pb.h"
30 #include "attestation/server/database_impl.h"
31
32 namespace {
33
34 #ifndef USE_TEST_ACA
35 const char kACAWebOrigin[] = "https://chromeos-ca.gstatic.com";
36 #else
37 const char kACAWebOrigin[] = "https://asbestos-qa.corp.google.com";
38 #endif
39 const size_t kNonceSize = 20; // As per TPM_NONCE definition.
40 const int kNumTemporalValues = 5;
41
42 } // namespace
43
44 namespace attestation {
45
AttestationService()46 AttestationService::AttestationService()
47 : attestation_ca_origin_(kACAWebOrigin), weak_factory_(this) {}
48
Initialize()49 bool AttestationService::Initialize() {
50 LOG(INFO) << "Attestation service started.";
51 worker_thread_.reset(new base::Thread("Attestation Service Worker"));
52 worker_thread_->StartWithOptions(
53 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
54 if (!tpm_utility_) {
55 default_tpm_utility_.reset(new TpmUtilityV1());
56 if (!default_tpm_utility_->Initialize()) {
57 return false;
58 }
59 tpm_utility_ = default_tpm_utility_.get();
60 }
61 if (!crypto_utility_) {
62 default_crypto_utility_.reset(new CryptoUtilityImpl(tpm_utility_));
63 crypto_utility_ = default_crypto_utility_.get();
64 }
65 if (!database_) {
66 default_database_.reset(new DatabaseImpl(crypto_utility_));
67 worker_thread_->task_runner()->PostTask(
68 FROM_HERE, base::Bind(&DatabaseImpl::Initialize,
69 base::Unretained(default_database_.get())));
70 database_ = default_database_.get();
71 }
72 if (!key_store_) {
73 pkcs11_token_manager_.reset(new chaps::TokenManagerClient());
74 default_key_store_.reset(new Pkcs11KeyStore(pkcs11_token_manager_.get()));
75 key_store_ = default_key_store_.get();
76 }
77 return true;
78 }
79
CreateGoogleAttestedKey(const CreateGoogleAttestedKeyRequest & request,const CreateGoogleAttestedKeyCallback & callback)80 void AttestationService::CreateGoogleAttestedKey(
81 const CreateGoogleAttestedKeyRequest& request,
82 const CreateGoogleAttestedKeyCallback& callback) {
83 auto result = std::make_shared<CreateGoogleAttestedKeyReply>();
84 base::Closure task =
85 base::Bind(&AttestationService::CreateGoogleAttestedKeyTask,
86 base::Unretained(this), request, result);
87 base::Closure reply = base::Bind(
88 &AttestationService::TaskRelayCallback<CreateGoogleAttestedKeyReply>,
89 GetWeakPtr(), callback, result);
90 worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
91 }
92
CreateGoogleAttestedKeyTask(const CreateGoogleAttestedKeyRequest & request,const std::shared_ptr<CreateGoogleAttestedKeyReply> & result)93 void AttestationService::CreateGoogleAttestedKeyTask(
94 const CreateGoogleAttestedKeyRequest& request,
95 const std::shared_ptr<CreateGoogleAttestedKeyReply>& result) {
96 LOG(INFO) << "Creating attested key: " << request.key_label();
97 if (!IsPreparedForEnrollment()) {
98 LOG(ERROR) << "Attestation: TPM is not ready.";
99 result->set_status(STATUS_NOT_READY);
100 return;
101 }
102 if (!IsEnrolled()) {
103 std::string enroll_request;
104 if (!CreateEnrollRequest(&enroll_request)) {
105 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
106 return;
107 }
108 std::string enroll_reply;
109 if (!SendACARequestAndBlock(kEnroll, enroll_request, &enroll_reply)) {
110 result->set_status(STATUS_CA_NOT_AVAILABLE);
111 return;
112 }
113 std::string server_error;
114 if (!FinishEnroll(enroll_reply, &server_error)) {
115 if (server_error.empty()) {
116 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
117 return;
118 }
119 result->set_status(STATUS_REQUEST_DENIED_BY_CA);
120 result->set_server_error(server_error);
121 return;
122 }
123 }
124 CertifiedKey key;
125 if (!CreateKey(request.username(), request.key_label(), request.key_type(),
126 request.key_usage(), &key)) {
127 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
128 return;
129 }
130 std::string certificate_request;
131 std::string message_id;
132 if (!CreateCertificateRequest(request.username(), key,
133 request.certificate_profile(), request.origin(),
134 &certificate_request, &message_id)) {
135 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
136 return;
137 }
138 std::string certificate_reply;
139 if (!SendACARequestAndBlock(kGetCertificate, certificate_request,
140 &certificate_reply)) {
141 result->set_status(STATUS_CA_NOT_AVAILABLE);
142 return;
143 }
144 std::string certificate_chain;
145 std::string server_error;
146 if (!FinishCertificateRequest(certificate_reply, request.username(),
147 request.key_label(), message_id, &key,
148 &certificate_chain, &server_error)) {
149 if (server_error.empty()) {
150 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
151 return;
152 }
153 result->set_status(STATUS_REQUEST_DENIED_BY_CA);
154 result->set_server_error(server_error);
155 return;
156 }
157 result->set_certificate_chain(certificate_chain);
158 }
159
GetKeyInfo(const GetKeyInfoRequest & request,const GetKeyInfoCallback & callback)160 void AttestationService::GetKeyInfo(const GetKeyInfoRequest& request,
161 const GetKeyInfoCallback& callback) {
162 auto result = std::make_shared<GetKeyInfoReply>();
163 base::Closure task = base::Bind(&AttestationService::GetKeyInfoTask,
164 base::Unretained(this), request, result);
165 base::Closure reply =
166 base::Bind(&AttestationService::TaskRelayCallback<GetKeyInfoReply>,
167 GetWeakPtr(), callback, result);
168 worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
169 }
170
GetKeyInfoTask(const GetKeyInfoRequest & request,const std::shared_ptr<GetKeyInfoReply> & result)171 void AttestationService::GetKeyInfoTask(
172 const GetKeyInfoRequest& request,
173 const std::shared_ptr<GetKeyInfoReply>& result) {
174 CertifiedKey key;
175 if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
176 result->set_status(STATUS_INVALID_PARAMETER);
177 return;
178 }
179 std::string public_key_info;
180 if (!GetSubjectPublicKeyInfo(key.key_type(), key.public_key(),
181 &public_key_info)) {
182 LOG(ERROR) << __func__ << ": Bad public key.";
183 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
184 return;
185 }
186 result->set_key_type(key.key_type());
187 result->set_key_usage(key.key_usage());
188 result->set_public_key(public_key_info);
189 result->set_certify_info(key.certified_key_info());
190 result->set_certify_info_signature(key.certified_key_proof());
191 if (key.has_intermediate_ca_cert()) {
192 result->set_certificate(CreatePEMCertificateChain(key));
193 } else {
194 result->set_certificate(key.certified_key_credential());
195 }
196 }
197
GetEndorsementInfo(const GetEndorsementInfoRequest & request,const GetEndorsementInfoCallback & callback)198 void AttestationService::GetEndorsementInfo(
199 const GetEndorsementInfoRequest& request,
200 const GetEndorsementInfoCallback& callback) {
201 auto result = std::make_shared<GetEndorsementInfoReply>();
202 base::Closure task = base::Bind(&AttestationService::GetEndorsementInfoTask,
203 base::Unretained(this), request, result);
204 base::Closure reply = base::Bind(
205 &AttestationService::TaskRelayCallback<GetEndorsementInfoReply>,
206 GetWeakPtr(), callback, result);
207 worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
208 }
209
GetEndorsementInfoTask(const GetEndorsementInfoRequest & request,const std::shared_ptr<GetEndorsementInfoReply> & result)210 void AttestationService::GetEndorsementInfoTask(
211 const GetEndorsementInfoRequest& request,
212 const std::shared_ptr<GetEndorsementInfoReply>& result) {
213 if (request.key_type() != KEY_TYPE_RSA) {
214 result->set_status(STATUS_INVALID_PARAMETER);
215 return;
216 }
217 auto database_pb = database_->GetProtobuf();
218 if (!database_pb.has_credentials() ||
219 !database_pb.credentials().has_endorsement_public_key()) {
220 // Try to read the public key directly.
221 std::string public_key;
222 if (!tpm_utility_->GetEndorsementPublicKey(&public_key)) {
223 result->set_status(STATUS_NOT_AVAILABLE);
224 return;
225 }
226 database_pb.mutable_credentials()->set_endorsement_public_key(public_key);
227 }
228 std::string public_key_info;
229 if (!GetSubjectPublicKeyInfo(
230 request.key_type(),
231 database_pb.credentials().endorsement_public_key(),
232 &public_key_info)) {
233 LOG(ERROR) << __func__ << ": Bad public key.";
234 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
235 return;
236 }
237 result->set_ek_public_key(public_key_info);
238 if (database_pb.credentials().has_endorsement_credential()) {
239 result->set_ek_certificate(
240 database_pb.credentials().endorsement_credential());
241 }
242 }
243
GetAttestationKeyInfo(const GetAttestationKeyInfoRequest & request,const GetAttestationKeyInfoCallback & callback)244 void AttestationService::GetAttestationKeyInfo(
245 const GetAttestationKeyInfoRequest& request,
246 const GetAttestationKeyInfoCallback& callback) {
247 auto result = std::make_shared<GetAttestationKeyInfoReply>();
248 base::Closure task =
249 base::Bind(&AttestationService::GetAttestationKeyInfoTask,
250 base::Unretained(this), request, result);
251 base::Closure reply = base::Bind(
252 &AttestationService::TaskRelayCallback<GetAttestationKeyInfoReply>,
253 GetWeakPtr(), callback, result);
254 worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
255 }
256
GetAttestationKeyInfoTask(const GetAttestationKeyInfoRequest & request,const std::shared_ptr<GetAttestationKeyInfoReply> & result)257 void AttestationService::GetAttestationKeyInfoTask(
258 const GetAttestationKeyInfoRequest& request,
259 const std::shared_ptr<GetAttestationKeyInfoReply>& result) {
260 if (request.key_type() != KEY_TYPE_RSA) {
261 result->set_status(STATUS_INVALID_PARAMETER);
262 return;
263 }
264 auto database_pb = database_->GetProtobuf();
265 if (!IsPreparedForEnrollment() || !database_pb.has_identity_key()) {
266 result->set_status(STATUS_NOT_AVAILABLE);
267 return;
268 }
269 if (database_pb.identity_key().has_identity_public_key()) {
270 std::string public_key_info;
271 if (!GetSubjectPublicKeyInfo(
272 request.key_type(),
273 database_pb.identity_key().identity_public_key(),
274 &public_key_info)) {
275 LOG(ERROR) << __func__ << ": Bad public key.";
276 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
277 return;
278 }
279 result->set_public_key(public_key_info);
280 }
281 if (database_pb.has_identity_binding() &&
282 database_pb.identity_binding().has_identity_public_key()) {
283 result->set_public_key_tpm_format(
284 database_pb.identity_binding().identity_public_key());
285 }
286 if (database_pb.identity_key().has_identity_credential()) {
287 result->set_certificate(database_pb.identity_key().identity_credential());
288 }
289 if (database_pb.has_pcr0_quote()) {
290 *result->mutable_pcr0_quote() = database_pb.pcr0_quote();
291 }
292 if (database_pb.has_pcr1_quote()) {
293 *result->mutable_pcr1_quote() = database_pb.pcr1_quote();
294 }
295 }
296
ActivateAttestationKey(const ActivateAttestationKeyRequest & request,const ActivateAttestationKeyCallback & callback)297 void AttestationService::ActivateAttestationKey(
298 const ActivateAttestationKeyRequest& request,
299 const ActivateAttestationKeyCallback& callback) {
300 auto result = std::make_shared<ActivateAttestationKeyReply>();
301 base::Closure task =
302 base::Bind(&AttestationService::ActivateAttestationKeyTask,
303 base::Unretained(this), request, result);
304 base::Closure reply = base::Bind(
305 &AttestationService::TaskRelayCallback<ActivateAttestationKeyReply>,
306 GetWeakPtr(), callback, result);
307 worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
308 }
309
ActivateAttestationKeyTask(const ActivateAttestationKeyRequest & request,const std::shared_ptr<ActivateAttestationKeyReply> & result)310 void AttestationService::ActivateAttestationKeyTask(
311 const ActivateAttestationKeyRequest& request,
312 const std::shared_ptr<ActivateAttestationKeyReply>& result) {
313 if (request.key_type() != KEY_TYPE_RSA) {
314 result->set_status(STATUS_INVALID_PARAMETER);
315 return;
316 }
317 std::string certificate;
318 auto database_pb = database_->GetProtobuf();
319 if (!tpm_utility_->ActivateIdentity(
320 database_pb.delegate().blob(), database_pb.delegate().secret(),
321 database_pb.identity_key().identity_key_blob(),
322 request.encrypted_certificate().asym_ca_contents(),
323 request.encrypted_certificate().sym_ca_attestation(), &certificate)) {
324 LOG(ERROR) << __func__ << ": Failed to activate identity.";
325 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
326 return;
327 }
328 if (request.save_certificate()) {
329 database_->GetMutableProtobuf()
330 ->mutable_identity_key()
331 ->set_identity_credential(certificate);
332 if (!database_->SaveChanges()) {
333 LOG(ERROR) << __func__ << ": Failed to persist database changes.";
334 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
335 }
336 }
337 result->set_certificate(certificate);
338 }
339
CreateCertifiableKey(const CreateCertifiableKeyRequest & request,const CreateCertifiableKeyCallback & callback)340 void AttestationService::CreateCertifiableKey(
341 const CreateCertifiableKeyRequest& request,
342 const CreateCertifiableKeyCallback& callback) {
343 auto result = std::make_shared<CreateCertifiableKeyReply>();
344 base::Closure task = base::Bind(&AttestationService::CreateCertifiableKeyTask,
345 base::Unretained(this), request, result);
346 base::Closure reply = base::Bind(
347 &AttestationService::TaskRelayCallback<CreateCertifiableKeyReply>,
348 GetWeakPtr(), callback, result);
349 worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
350 }
351
CreateCertifiableKeyTask(const CreateCertifiableKeyRequest & request,const std::shared_ptr<CreateCertifiableKeyReply> & result)352 void AttestationService::CreateCertifiableKeyTask(
353 const CreateCertifiableKeyRequest& request,
354 const std::shared_ptr<CreateCertifiableKeyReply>& result) {
355 CertifiedKey key;
356 if (!CreateKey(request.username(), request.key_label(), request.key_type(),
357 request.key_usage(), &key)) {
358 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
359 return;
360 }
361 std::string public_key_info;
362 if (!GetSubjectPublicKeyInfo(key.key_type(), key.public_key(),
363 &public_key_info)) {
364 LOG(ERROR) << __func__ << ": Bad public key.";
365 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
366 return;
367 }
368 result->set_public_key(public_key_info);
369 result->set_certify_info(key.certified_key_info());
370 result->set_certify_info_signature(key.certified_key_proof());
371 }
372
Decrypt(const DecryptRequest & request,const DecryptCallback & callback)373 void AttestationService::Decrypt(const DecryptRequest& request,
374 const DecryptCallback& callback) {
375 auto result = std::make_shared<DecryptReply>();
376 base::Closure task = base::Bind(&AttestationService::DecryptTask,
377 base::Unretained(this), request, result);
378 base::Closure reply =
379 base::Bind(&AttestationService::TaskRelayCallback<DecryptReply>,
380 GetWeakPtr(), callback, result);
381 worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
382 }
383
DecryptTask(const DecryptRequest & request,const std::shared_ptr<DecryptReply> & result)384 void AttestationService::DecryptTask(
385 const DecryptRequest& request,
386 const std::shared_ptr<DecryptReply>& result) {
387 CertifiedKey key;
388 if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
389 result->set_status(STATUS_INVALID_PARAMETER);
390 return;
391 }
392 std::string data;
393 if (!tpm_utility_->Unbind(key.key_blob(), request.encrypted_data(), &data)) {
394 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
395 return;
396 }
397 result->set_decrypted_data(data);
398 }
399
Sign(const SignRequest & request,const SignCallback & callback)400 void AttestationService::Sign(const SignRequest& request,
401 const SignCallback& callback) {
402 auto result = std::make_shared<SignReply>();
403 base::Closure task = base::Bind(&AttestationService::SignTask,
404 base::Unretained(this), request, result);
405 base::Closure reply =
406 base::Bind(&AttestationService::TaskRelayCallback<SignReply>,
407 GetWeakPtr(), callback, result);
408 worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
409 }
410
SignTask(const SignRequest & request,const std::shared_ptr<SignReply> & result)411 void AttestationService::SignTask(const SignRequest& request,
412 const std::shared_ptr<SignReply>& result) {
413 CertifiedKey key;
414 if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
415 result->set_status(STATUS_INVALID_PARAMETER);
416 return;
417 }
418 std::string signature;
419 if (!tpm_utility_->Sign(key.key_blob(), request.data_to_sign(), &signature)) {
420 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
421 return;
422 }
423 result->set_signature(signature);
424 }
425
RegisterKeyWithChapsToken(const RegisterKeyWithChapsTokenRequest & request,const RegisterKeyWithChapsTokenCallback & callback)426 void AttestationService::RegisterKeyWithChapsToken(
427 const RegisterKeyWithChapsTokenRequest& request,
428 const RegisterKeyWithChapsTokenCallback& callback) {
429 auto result = std::make_shared<RegisterKeyWithChapsTokenReply>();
430 base::Closure task =
431 base::Bind(&AttestationService::RegisterKeyWithChapsTokenTask,
432 base::Unretained(this), request, result);
433 base::Closure reply = base::Bind(
434 &AttestationService::TaskRelayCallback<RegisterKeyWithChapsTokenReply>,
435 GetWeakPtr(), callback, result);
436 worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
437 }
438
RegisterKeyWithChapsTokenTask(const RegisterKeyWithChapsTokenRequest & request,const std::shared_ptr<RegisterKeyWithChapsTokenReply> & result)439 void AttestationService::RegisterKeyWithChapsTokenTask(
440 const RegisterKeyWithChapsTokenRequest& request,
441 const std::shared_ptr<RegisterKeyWithChapsTokenReply>& result) {
442 CertifiedKey key;
443 if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
444 result->set_status(STATUS_INVALID_PARAMETER);
445 return;
446 }
447 if (!key_store_->Register(request.username(), request.key_label(),
448 key.key_type(), key.key_usage(), key.key_blob(),
449 key.public_key(), key.certified_key_credential())) {
450 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
451 return;
452 }
453 if (key.has_intermediate_ca_cert() &&
454 !key_store_->RegisterCertificate(request.username(),
455 key.intermediate_ca_cert())) {
456 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
457 return;
458 }
459 for (int i = 0; i < key.additional_intermediate_ca_cert_size(); ++i) {
460 if (!key_store_->RegisterCertificate(
461 request.username(), key.additional_intermediate_ca_cert(i))) {
462 result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
463 return;
464 }
465 }
466 DeleteKey(request.username(), request.key_label());
467 }
468
IsPreparedForEnrollment()469 bool AttestationService::IsPreparedForEnrollment() {
470 if (!tpm_utility_->IsTpmReady()) {
471 return false;
472 }
473 auto database_pb = database_->GetProtobuf();
474 if (!database_pb.has_credentials()) {
475 return false;
476 }
477 return (
478 database_pb.credentials().has_endorsement_credential() ||
479 database_pb.credentials().has_default_encrypted_endorsement_credential());
480 }
481
IsEnrolled()482 bool AttestationService::IsEnrolled() {
483 auto database_pb = database_->GetProtobuf();
484 return database_pb.has_identity_key() &&
485 database_pb.identity_key().has_identity_credential();
486 }
487
CreateEnrollRequest(std::string * enroll_request)488 bool AttestationService::CreateEnrollRequest(std::string* enroll_request) {
489 if (!IsPreparedForEnrollment()) {
490 LOG(ERROR) << __func__ << ": Enrollment is not possible, attestation data "
491 << "does not exist.";
492 return false;
493 }
494 auto database_pb = database_->GetProtobuf();
495 AttestationEnrollmentRequest request_pb;
496 *request_pb.mutable_encrypted_endorsement_credential() =
497 database_pb.credentials().default_encrypted_endorsement_credential();
498 request_pb.set_identity_public_key(
499 database_pb.identity_binding().identity_public_key());
500 *request_pb.mutable_pcr0_quote() = database_pb.pcr0_quote();
501 *request_pb.mutable_pcr1_quote() = database_pb.pcr1_quote();
502 if (!request_pb.SerializeToString(enroll_request)) {
503 LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
504 return false;
505 }
506 return true;
507 }
508
FinishEnroll(const std::string & enroll_response,std::string * server_error)509 bool AttestationService::FinishEnroll(const std::string& enroll_response,
510 std::string* server_error) {
511 if (!tpm_utility_->IsTpmReady()) {
512 return false;
513 }
514 AttestationEnrollmentResponse response_pb;
515 if (!response_pb.ParseFromString(enroll_response)) {
516 LOG(ERROR) << __func__ << ": Failed to parse response from CA.";
517 return false;
518 }
519 if (response_pb.status() != OK) {
520 *server_error = response_pb.detail();
521 LOG(ERROR) << __func__
522 << ": Error received from CA: " << response_pb.detail();
523 return false;
524 }
525 std::string credential;
526 auto database_pb = database_->GetProtobuf();
527 if (!tpm_utility_->ActivateIdentity(
528 database_pb.delegate().blob(), database_pb.delegate().secret(),
529 database_pb.identity_key().identity_key_blob(),
530 response_pb.encrypted_identity_credential().asym_ca_contents(),
531 response_pb.encrypted_identity_credential().sym_ca_attestation(),
532 &credential)) {
533 LOG(ERROR) << __func__ << ": Failed to activate identity.";
534 return false;
535 }
536 database_->GetMutableProtobuf()
537 ->mutable_identity_key()
538 ->set_identity_credential(credential);
539 if (!database_->SaveChanges()) {
540 LOG(ERROR) << __func__ << ": Failed to persist database changes.";
541 return false;
542 }
543 LOG(INFO) << "Attestation: Enrollment complete.";
544 return true;
545 }
546
CreateCertificateRequest(const std::string & username,const CertifiedKey & key,CertificateProfile profile,const std::string & origin,std::string * certificate_request,std::string * message_id)547 bool AttestationService::CreateCertificateRequest(
548 const std::string& username,
549 const CertifiedKey& key,
550 CertificateProfile profile,
551 const std::string& origin,
552 std::string* certificate_request,
553 std::string* message_id) {
554 if (!tpm_utility_->IsTpmReady()) {
555 return false;
556 }
557 if (!IsEnrolled()) {
558 LOG(ERROR) << __func__ << ": Device is not enrolled for attestation.";
559 return false;
560 }
561 AttestationCertificateRequest request_pb;
562 if (!crypto_utility_->GetRandom(kNonceSize, message_id)) {
563 LOG(ERROR) << __func__ << ": GetRandom(message_id) failed.";
564 return false;
565 }
566 request_pb.set_message_id(*message_id);
567 auto database_pb = database_->GetProtobuf();
568 request_pb.set_identity_credential(
569 database_pb.identity_key().identity_credential());
570 request_pb.set_profile(profile);
571 if (!origin.empty() &&
572 (profile == CONTENT_PROTECTION_CERTIFICATE_WITH_STABLE_ID)) {
573 request_pb.set_origin(origin);
574 request_pb.set_temporal_index(ChooseTemporalIndex(username, origin));
575 }
576 request_pb.set_certified_public_key(key.public_key_tpm_format());
577 request_pb.set_certified_key_info(key.certified_key_info());
578 request_pb.set_certified_key_proof(key.certified_key_proof());
579 if (!request_pb.SerializeToString(certificate_request)) {
580 LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
581 return false;
582 }
583 return true;
584 }
585
FinishCertificateRequest(const std::string & certificate_response,const std::string & username,const std::string & key_label,const std::string & message_id,CertifiedKey * key,std::string * certificate_chain,std::string * server_error)586 bool AttestationService::FinishCertificateRequest(
587 const std::string& certificate_response,
588 const std::string& username,
589 const std::string& key_label,
590 const std::string& message_id,
591 CertifiedKey* key,
592 std::string* certificate_chain,
593 std::string* server_error) {
594 if (!tpm_utility_->IsTpmReady()) {
595 return false;
596 }
597 AttestationCertificateResponse response_pb;
598 if (!response_pb.ParseFromString(certificate_response)) {
599 LOG(ERROR) << __func__ << ": Failed to parse response from Privacy CA.";
600 return false;
601 }
602 if (response_pb.status() != OK) {
603 *server_error = response_pb.detail();
604 LOG(ERROR) << __func__
605 << ": Error received from Privacy CA: " << response_pb.detail();
606 return false;
607 }
608 if (message_id != response_pb.message_id()) {
609 LOG(ERROR) << __func__ << ": Message ID mismatch.";
610 return false;
611 }
612
613 // Finish populating the CertifiedKey protobuf and store it.
614 key->set_certified_key_credential(response_pb.certified_key_credential());
615 key->set_intermediate_ca_cert(response_pb.intermediate_ca_cert());
616 key->mutable_additional_intermediate_ca_cert()->MergeFrom(
617 response_pb.additional_intermediate_ca_cert());
618 if (!SaveKey(username, key_label, *key)) {
619 return false;
620 }
621 LOG(INFO) << "Attestation: Certified key credential received and stored.";
622 *certificate_chain = CreatePEMCertificateChain(*key);
623 return true;
624 }
625
SendACARequestAndBlock(ACARequestType request_type,const std::string & request,std::string * reply)626 bool AttestationService::SendACARequestAndBlock(ACARequestType request_type,
627 const std::string& request,
628 std::string* reply) {
629 std::shared_ptr<brillo::http::Transport> transport = http_transport_;
630 if (!transport) {
631 transport = brillo::http::Transport::CreateDefault();
632 }
633 std::unique_ptr<brillo::http::Response> response = PostBinaryAndBlock(
634 GetACAURL(request_type), request.data(), request.size(),
635 brillo::mime::application::kOctet_stream, {}, // headers
636 transport,
637 nullptr); // error
638 if (!response || !response->IsSuccessful()) {
639 LOG(ERROR) << "HTTP request to Attestation CA failed.";
640 return false;
641 }
642 *reply = response->ExtractDataAsString();
643 return true;
644 }
645
FindKeyByLabel(const std::string & username,const std::string & key_label,CertifiedKey * key)646 bool AttestationService::FindKeyByLabel(const std::string& username,
647 const std::string& key_label,
648 CertifiedKey* key) {
649 if (!username.empty()) {
650 std::string key_data;
651 if (!key_store_->Read(username, key_label, &key_data)) {
652 LOG(INFO) << "Key not found: " << key_label;
653 return false;
654 }
655 if (key && !key->ParseFromString(key_data)) {
656 LOG(ERROR) << "Failed to parse key: " << key_label;
657 return false;
658 }
659 return true;
660 }
661 auto database_pb = database_->GetProtobuf();
662 for (int i = 0; i < database_pb.device_keys_size(); ++i) {
663 if (database_pb.device_keys(i).key_name() == key_label) {
664 *key = database_pb.device_keys(i);
665 return true;
666 }
667 }
668 LOG(INFO) << "Key not found: " << key_label;
669 return false;
670 }
671
CreateKey(const std::string & username,const std::string & key_label,KeyType key_type,KeyUsage key_usage,CertifiedKey * key)672 bool AttestationService::CreateKey(const std::string& username,
673 const std::string& key_label,
674 KeyType key_type,
675 KeyUsage key_usage,
676 CertifiedKey* key) {
677 std::string nonce;
678 if (!crypto_utility_->GetRandom(kNonceSize, &nonce)) {
679 LOG(ERROR) << __func__ << ": GetRandom(nonce) failed.";
680 return false;
681 }
682 std::string key_blob;
683 std::string public_key;
684 std::string public_key_tpm_format;
685 std::string key_info;
686 std::string proof;
687 auto database_pb = database_->GetProtobuf();
688 if (!tpm_utility_->CreateCertifiedKey(
689 key_type, key_usage, database_pb.identity_key().identity_key_blob(),
690 nonce, &key_blob, &public_key, &public_key_tpm_format, &key_info,
691 &proof)) {
692 return false;
693 }
694 key->set_key_blob(key_blob);
695 key->set_public_key(public_key);
696 key->set_key_name(key_label);
697 key->set_public_key_tpm_format(public_key_tpm_format);
698 key->set_certified_key_info(key_info);
699 key->set_certified_key_proof(proof);
700 return SaveKey(username, key_label, *key);
701 }
702
SaveKey(const std::string & username,const std::string & key_label,const CertifiedKey & key)703 bool AttestationService::SaveKey(const std::string& username,
704 const std::string& key_label,
705 const CertifiedKey& key) {
706 if (!username.empty()) {
707 std::string key_data;
708 if (!key.SerializeToString(&key_data)) {
709 LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
710 return false;
711 }
712 if (!key_store_->Write(username, key_label, key_data)) {
713 LOG(ERROR) << __func__ << ": Failed to store certified key for user.";
714 return false;
715 }
716 } else {
717 if (!AddDeviceKey(key_label, key)) {
718 LOG(ERROR) << __func__ << ": Failed to store certified key for device.";
719 return false;
720 }
721 }
722 return true;
723 }
724
DeleteKey(const std::string & username,const std::string & key_label)725 void AttestationService::DeleteKey(const std::string& username,
726 const std::string& key_label) {
727 if (!username.empty()) {
728 key_store_->Delete(username, key_label);
729 } else {
730 RemoveDeviceKey(key_label);
731 }
732 }
733
AddDeviceKey(const std::string & key_label,const CertifiedKey & key)734 bool AttestationService::AddDeviceKey(const std::string& key_label,
735 const CertifiedKey& key) {
736 // If a key by this name already exists, reuse the field.
737 auto* database_pb = database_->GetMutableProtobuf();
738 bool found = false;
739 for (int i = 0; i < database_pb->device_keys_size(); ++i) {
740 if (database_pb->device_keys(i).key_name() == key_label) {
741 found = true;
742 *database_pb->mutable_device_keys(i) = key;
743 break;
744 }
745 }
746 if (!found)
747 *database_pb->add_device_keys() = key;
748 return database_->SaveChanges();
749 }
750
RemoveDeviceKey(const std::string & key_label)751 void AttestationService::RemoveDeviceKey(const std::string& key_label) {
752 auto* database_pb = database_->GetMutableProtobuf();
753 bool found = false;
754 for (int i = 0; i < database_pb->device_keys_size(); ++i) {
755 if (database_pb->device_keys(i).key_name() == key_label) {
756 found = true;
757 int last = database_pb->device_keys_size() - 1;
758 if (i < last) {
759 database_pb->mutable_device_keys()->SwapElements(i, last);
760 }
761 database_pb->mutable_device_keys()->RemoveLast();
762 break;
763 }
764 }
765 if (found) {
766 if (!database_->SaveChanges()) {
767 LOG(WARNING) << __func__ << ": Failed to persist key deletion.";
768 }
769 }
770 }
771
CreatePEMCertificateChain(const CertifiedKey & key)772 std::string AttestationService::CreatePEMCertificateChain(
773 const CertifiedKey& key) {
774 if (key.certified_key_credential().empty()) {
775 LOG(WARNING) << "Certificate is empty.";
776 return std::string();
777 }
778 std::string pem = CreatePEMCertificate(key.certified_key_credential());
779 if (!key.intermediate_ca_cert().empty()) {
780 pem += "\n";
781 pem += CreatePEMCertificate(key.intermediate_ca_cert());
782 }
783 for (int i = 0; i < key.additional_intermediate_ca_cert_size(); ++i) {
784 pem += "\n";
785 pem += CreatePEMCertificate(key.additional_intermediate_ca_cert(i));
786 }
787 return pem;
788 }
789
CreatePEMCertificate(const std::string & certificate)790 std::string AttestationService::CreatePEMCertificate(
791 const std::string& certificate) {
792 const char kBeginCertificate[] = "-----BEGIN CERTIFICATE-----\n";
793 const char kEndCertificate[] = "-----END CERTIFICATE-----";
794
795 std::string pem = kBeginCertificate;
796 pem += brillo::data_encoding::Base64EncodeWrapLines(certificate);
797 pem += kEndCertificate;
798 return pem;
799 }
800
ChooseTemporalIndex(const std::string & user,const std::string & origin)801 int AttestationService::ChooseTemporalIndex(const std::string& user,
802 const std::string& origin) {
803 std::string user_hash = crypto::SHA256HashString(user);
804 std::string origin_hash = crypto::SHA256HashString(origin);
805 int histogram[kNumTemporalValues] = {};
806 auto database_pb = database_->GetProtobuf();
807 for (int i = 0; i < database_pb.temporal_index_record_size(); ++i) {
808 const AttestationDatabase::TemporalIndexRecord& record =
809 database_pb.temporal_index_record(i);
810 // Ignore out-of-range index values.
811 if (record.temporal_index() < 0 ||
812 record.temporal_index() >= kNumTemporalValues)
813 continue;
814 if (record.origin_hash() == origin_hash) {
815 if (record.user_hash() == user_hash) {
816 // We've previously chosen this index for this user, reuse it.
817 return record.temporal_index();
818 } else {
819 // We've previously chosen this index for another user.
820 ++histogram[record.temporal_index()];
821 }
822 }
823 }
824 int least_used_index = 0;
825 for (int i = 1; i < kNumTemporalValues; ++i) {
826 if (histogram[i] < histogram[least_used_index])
827 least_used_index = i;
828 }
829 if (histogram[least_used_index] > 0) {
830 LOG(WARNING) << "Unique origin-specific identifiers have been exhausted.";
831 }
832 // Record our choice for later reference.
833 AttestationDatabase::TemporalIndexRecord* new_record =
834 database_pb.add_temporal_index_record();
835 new_record->set_origin_hash(origin_hash);
836 new_record->set_user_hash(user_hash);
837 new_record->set_temporal_index(least_used_index);
838 database_->SaveChanges();
839 return least_used_index;
840 }
841
GetACAURL(ACARequestType request_type) const842 std::string AttestationService::GetACAURL(ACARequestType request_type) const {
843 std::string url = attestation_ca_origin_;
844 switch (request_type) {
845 case kEnroll:
846 url += "/enroll";
847 break;
848 case kGetCertificate:
849 url += "/sign";
850 break;
851 default:
852 NOTREACHED();
853 }
854 return url;
855 }
856
GetSubjectPublicKeyInfo(KeyType key_type,const std::string & public_key,std::string * public_key_info) const857 bool AttestationService::GetSubjectPublicKeyInfo(
858 KeyType key_type,
859 const std::string& public_key,
860 std::string* public_key_info) const {
861 // Only RSA is supported currently.
862 if (key_type != KEY_TYPE_RSA) {
863 return false;
864 }
865 return crypto_utility_->GetRSASubjectPublicKeyInfo(public_key,
866 public_key_info);
867 }
868
GetWeakPtr()869 base::WeakPtr<AttestationService> AttestationService::GetWeakPtr() {
870 return weak_factory_.GetWeakPtr();
871 }
872
873 } // namespace attestation
874