13daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
23daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// Copyright (C) 2015 The Android Open Source Project
33daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
43daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// Licensed under the Apache License, Version 2.0 (the "License");
53daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// you may not use this file except in compliance with the License.
63daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// You may obtain a copy of the License at
73daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
83daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//      http://www.apache.org/licenses/LICENSE-2.0
93daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
103daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// Unless required by applicable law or agreed to in writing, software
113daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// distributed under the License is distributed on an "AS IS" BASIS,
123daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// See the License for the specific language governing permissions and
143daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// limitations under the License.
153daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
166bead48129845a2bc0d6ff347f3d7e232004d59Nam T. Nguyen
17ab0cddda9971f97781fc9f6cbc76095ba7542abfAlex Vakulenko#include "attestation/server/attestation_service.h"
186bead48129845a2bc0d6ff347f3d7e232004d59Nam T. Nguyen
19d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn#include <string>
20d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
210752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn#include <base/callback.h>
22e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko#include <brillo/bind_lambda.h>
23e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko#include <brillo/data_encoding.h>
24e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko#include <brillo/http/http_utils.h>
25e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko#include <brillo/mime_utils.h>
26d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn#include <crypto/sha2.h>
270752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
28d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn#include "attestation/common/attestation_ca.pb.h"
29d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn#include "attestation/common/database.pb.h"
3030a5bba00647d29e324111005deb76a0466f8c6bDarren Krahn#include "attestation/server/database_impl.h"
3130a5bba00647d29e324111005deb76a0466f8c6bDarren Krahn
32d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnnamespace {
33d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
34d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn#ifndef USE_TEST_ACA
35d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnconst char kACAWebOrigin[] = "https://chromeos-ca.gstatic.com";
36d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn#else
37d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnconst char kACAWebOrigin[] = "https://asbestos-qa.corp.google.com";
38d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn#endif
39d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnconst size_t kNonceSize = 20;  // As per TPM_NONCE definition.
40d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnconst int kNumTemporalValues = 5;
41d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
42d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}  // namespace
43d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
446bead48129845a2bc0d6ff347f3d7e232004d59Nam T. Nguyennamespace attestation {
456bead48129845a2bc0d6ff347f3d7e232004d59Nam T. Nguyen
46d66389850c33614ffbbbbc3f768621182fd853baDarren KrahnAttestationService::AttestationService()
47d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    : attestation_ca_origin_(kACAWebOrigin),
48d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      weak_factory_(this) {}
49d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
50b91fd4923f411705be97fbc5c0ada37481c0cd8dDarren Krahnbool AttestationService::Initialize() {
51d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  LOG(INFO) << "Attestation service started.";
52d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  worker_thread_.reset(new base::Thread("Attestation Service Worker"));
5391b43220439ab46096af0efc47f9b706abc3b108Darren Krahn  worker_thread_->StartWithOptions(
5491b43220439ab46096af0efc47f9b706abc3b108Darren Krahn      base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
5559d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn  if (!tpm_utility_) {
5659d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn    default_tpm_utility_.reset(new TpmUtilityV1());
5759d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn    if (!default_tpm_utility_->Initialize()) {
5859d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn      return false;
5959d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn    }
6059d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn    tpm_utility_ = default_tpm_utility_.get();
6159d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn  }
6259d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn  if (!crypto_utility_) {
6359d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn    default_crypto_utility_.reset(new CryptoUtilityImpl(tpm_utility_));
6459d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn    crypto_utility_ = default_crypto_utility_.get();
6559d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn  }
6630a5bba00647d29e324111005deb76a0466f8c6bDarren Krahn  if (!database_) {
67d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    default_database_.reset(new DatabaseImpl(crypto_utility_));
6891b43220439ab46096af0efc47f9b706abc3b108Darren Krahn    worker_thread_->task_runner()->PostTask(FROM_HERE, base::Bind(
6991b43220439ab46096af0efc47f9b706abc3b108Darren Krahn        &DatabaseImpl::Initialize,
7091b43220439ab46096af0efc47f9b706abc3b108Darren Krahn        base::Unretained(default_database_.get())));
7130a5bba00647d29e324111005deb76a0466f8c6bDarren Krahn    database_ = default_database_.get();
7230a5bba00647d29e324111005deb76a0466f8c6bDarren Krahn  }
7359d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn  if (!key_store_) {
7459d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn    pkcs11_token_manager_.reset(new chaps::TokenManagerClient());
7559d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn    default_key_store_.reset(new Pkcs11KeyStore(pkcs11_token_manager_.get()));
7659d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn    key_store_ = default_key_store_.get();
7759d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn  }
78b91fd4923f411705be97fbc5c0ada37481c0cd8dDarren Krahn  return true;
796bead48129845a2bc0d6ff347f3d7e232004d59Nam T. Nguyen}
806bead48129845a2bc0d6ff347f3d7e232004d59Nam T. Nguyen
810752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahnvoid AttestationService::CreateGoogleAttestedKey(
82b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    const CreateGoogleAttestedKeyRequest& request,
83d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    const CreateGoogleAttestedKeyCallback& callback) {
84b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn  auto result = std::make_shared<CreateGoogleAttestedKeyReply>();
85d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  base::Closure task = base::Bind(
86d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      &AttestationService::CreateGoogleAttestedKeyTask,
87d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      base::Unretained(this),
88b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn      request,
89d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      result);
90d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  base::Closure reply = base::Bind(
91cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      &AttestationService::TaskRelayCallback<CreateGoogleAttestedKeyReply>,
92d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      GetWeakPtr(),
93d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      callback,
94d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      result);
95d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
96d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
97d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
98d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnvoid AttestationService::CreateGoogleAttestedKeyTask(
99b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    const CreateGoogleAttestedKeyRequest& request,
100b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    const std::shared_ptr<CreateGoogleAttestedKeyReply>& result) {
101b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn  LOG(INFO) << "Creating attested key: " << request.key_label();
102d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!IsPreparedForEnrollment()) {
103d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << "Attestation: TPM is not ready.";
104b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    result->set_status(STATUS_NOT_READY);
105d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return;
106d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
107d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!IsEnrolled()) {
108d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    std::string enroll_request;
109d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (!CreateEnrollRequest(&enroll_request)) {
110b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
111d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      return;
112d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
113d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    std::string enroll_reply;
114d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (!SendACARequestAndBlock(kEnroll,
115d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                enroll_request,
116d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                &enroll_reply)) {
117b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn      result->set_status(STATUS_CA_NOT_AVAILABLE);
118d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      return;
119d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
120d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    std::string server_error;
121b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    if (!FinishEnroll(enroll_reply, &server_error)) {
1222e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      if (server_error.empty()) {
1232e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
1242e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        return;
1252e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      }
126b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn      result->set_status(STATUS_REQUEST_DENIED_BY_CA);
127b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn      result->set_server_error(server_error);
128d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      return;
129d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
130d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
13162c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  CertifiedKey key;
132b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn  if (!CreateKey(request.username(), request.key_label(), request.key_type(),
13362c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn                 request.key_usage(), &key)) {
134b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
13508d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn    return;
136d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
137d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string certificate_request;
138d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string message_id;
139b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn  if (!CreateCertificateRequest(request.username(),
14062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn                                key,
141b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn                                request.certificate_profile(),
142b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn                                request.origin(),
143d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                &certificate_request,
144d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                &message_id)) {
145b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
146d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return;
147d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
148d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string certificate_reply;
149d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!SendACARequestAndBlock(kGetCertificate,
150d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                              certificate_request,
151d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                              &certificate_reply)) {
152b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    result->set_status(STATUS_CA_NOT_AVAILABLE);
153d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return;
154d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
155d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string certificate_chain;
156d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string server_error;
157d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!FinishCertificateRequest(certificate_reply,
158b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn                                request.username(),
159b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn                                request.key_label(),
160d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                message_id,
16162c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn                                &key,
162b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn                                &certificate_chain,
163b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn                                &server_error)) {
1642e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    if (server_error.empty()) {
1652e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
1662e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      return;
1672e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    }
168b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    result->set_status(STATUS_REQUEST_DENIED_BY_CA);
169b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    result->set_server_error(server_error);
170d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return;
171d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
172b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn  result->set_certificate_chain(certificate_chain);
173d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
174d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
1756222defa52eb13c0d90673f642f2647f7753478bDarren Krahnvoid AttestationService::GetKeyInfo(const GetKeyInfoRequest& request,
1766222defa52eb13c0d90673f642f2647f7753478bDarren Krahn                                    const GetKeyInfoCallback& callback) {
1776222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  auto result = std::make_shared<GetKeyInfoReply>();
1786222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  base::Closure task = base::Bind(
1796222defa52eb13c0d90673f642f2647f7753478bDarren Krahn      &AttestationService::GetKeyInfoTask,
1806222defa52eb13c0d90673f642f2647f7753478bDarren Krahn      base::Unretained(this),
1816222defa52eb13c0d90673f642f2647f7753478bDarren Krahn      request,
1826222defa52eb13c0d90673f642f2647f7753478bDarren Krahn      result);
1836222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  base::Closure reply = base::Bind(
184cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      &AttestationService::TaskRelayCallback<GetKeyInfoReply>,
1856222defa52eb13c0d90673f642f2647f7753478bDarren Krahn      GetWeakPtr(),
1866222defa52eb13c0d90673f642f2647f7753478bDarren Krahn      callback,
1876222defa52eb13c0d90673f642f2647f7753478bDarren Krahn      result);
1886222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
1896222defa52eb13c0d90673f642f2647f7753478bDarren Krahn}
1906222defa52eb13c0d90673f642f2647f7753478bDarren Krahn
1916222defa52eb13c0d90673f642f2647f7753478bDarren Krahnvoid AttestationService::GetKeyInfoTask(
1926222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    const GetKeyInfoRequest& request,
1936222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    const std::shared_ptr<GetKeyInfoReply>& result) {
1946222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  CertifiedKey key;
1956222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
1966222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    result->set_status(STATUS_INVALID_PARAMETER);
1976222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    return;
1986222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  }
1996222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  std::string public_key_info;
2006222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  if (!GetSubjectPublicKeyInfo(key.key_type(), key.public_key(),
2016222defa52eb13c0d90673f642f2647f7753478bDarren Krahn                               &public_key_info)) {
2026222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    LOG(ERROR) << __func__ << ": Bad public key.";
2036222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
2046222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    return;
2056222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  }
2066222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  result->set_key_type(key.key_type());
2076222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  result->set_key_usage(key.key_usage());
2086222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  result->set_public_key(public_key_info);
2096222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  result->set_certify_info(key.certified_key_info());
2106222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  result->set_certify_info_signature(key.certified_key_proof());
2116222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  if (key.has_intermediate_ca_cert()) {
2126222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    result->set_certificate(CreatePEMCertificateChain(key));
2136222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  } else {
2146222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    result->set_certificate(key.certified_key_credential());
2156222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  }
2166222defa52eb13c0d90673f642f2647f7753478bDarren Krahn}
2176222defa52eb13c0d90673f642f2647f7753478bDarren Krahn
218cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahnvoid AttestationService::GetEndorsementInfo(
219cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    const GetEndorsementInfoRequest& request,
220cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    const GetEndorsementInfoCallback& callback) {
221cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  auto result = std::make_shared<GetEndorsementInfoReply>();
222cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  base::Closure task = base::Bind(
223cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      &AttestationService::GetEndorsementInfoTask,
224cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      base::Unretained(this),
225cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      request,
226cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      result);
227cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  base::Closure reply = base::Bind(
228cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      &AttestationService::TaskRelayCallback<GetEndorsementInfoReply>,
229cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      GetWeakPtr(),
230cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      callback,
231cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      result);
232cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
233cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn}
234cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn
235cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahnvoid AttestationService::GetEndorsementInfoTask(
236cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    const GetEndorsementInfoRequest& request,
237cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    const std::shared_ptr<GetEndorsementInfoReply>& result) {
238cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  if (request.key_type() != KEY_TYPE_RSA) {
239cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    result->set_status(STATUS_INVALID_PARAMETER);
240cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    return;
241cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  }
242cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  auto database_pb = database_->GetProtobuf();
243cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  if (!database_pb.has_credentials() ||
244cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      !database_pb.credentials().has_endorsement_public_key()) {
245cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    // Try to read the public key directly.
246cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    std::string public_key;
247cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    if (!tpm_utility_->GetEndorsementPublicKey(&public_key)) {
248cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      result->set_status(STATUS_NOT_AVAILABLE);
249cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      return;
250cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    }
251cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    database_pb.mutable_credentials()->set_endorsement_public_key(public_key);
252cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  }
253566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  std::string public_key_info;
254566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  if (!GetSubjectPublicKeyInfo(
255566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      request.key_type(),
256566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      database_pb.credentials().endorsement_public_key(),
257566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      &public_key_info)) {
258566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    LOG(ERROR) << __func__ << ": Bad public key.";
259566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
260566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    return;
261566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  }
262566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  result->set_ek_public_key(public_key_info);
263cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  if (database_pb.credentials().has_endorsement_credential()) {
264cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    result->set_ek_certificate(
265cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn        database_pb.credentials().endorsement_credential());
266cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  }
2676222defa52eb13c0d90673f642f2647f7753478bDarren Krahn}
2686222defa52eb13c0d90673f642f2647f7753478bDarren Krahn
269566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahnvoid AttestationService::GetAttestationKeyInfo(
270566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    const GetAttestationKeyInfoRequest& request,
271566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    const GetAttestationKeyInfoCallback& callback) {
272566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  auto result = std::make_shared<GetAttestationKeyInfoReply>();
273566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  base::Closure task = base::Bind(
274566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      &AttestationService::GetAttestationKeyInfoTask,
275566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      base::Unretained(this),
276566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      request,
277566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      result);
278566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  base::Closure reply = base::Bind(
279566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      &AttestationService::TaskRelayCallback<GetAttestationKeyInfoReply>,
280566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      GetWeakPtr(),
281566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      callback,
282566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      result);
283566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
284566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn}
285566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn
286566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahnvoid AttestationService::GetAttestationKeyInfoTask(
287566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    const GetAttestationKeyInfoRequest& request,
288566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    const std::shared_ptr<GetAttestationKeyInfoReply>& result) {
289566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  if (request.key_type() != KEY_TYPE_RSA) {
290566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    result->set_status(STATUS_INVALID_PARAMETER);
291566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    return;
292566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  }
293566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  auto database_pb = database_->GetProtobuf();
294566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  if (!IsPreparedForEnrollment() || !database_pb.has_identity_key()) {
295566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    result->set_status(STATUS_NOT_AVAILABLE);
296566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    return;
297566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  }
298566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  if (database_pb.identity_key().has_identity_public_key()) {
299566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    std::string public_key_info;
300566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    if (!GetSubjectPublicKeyInfo(
301566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn        request.key_type(),
302566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn        database_pb.identity_key().identity_public_key(),
303566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn        &public_key_info)) {
304566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      LOG(ERROR) << __func__ << ": Bad public key.";
305566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
306566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      return;
307566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    }
308566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    result->set_public_key(public_key_info);
309566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  }
3102e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  if (database_pb.has_identity_binding() &&
3112e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      database_pb.identity_binding().has_identity_public_key()) {
3122e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    result->set_public_key_tpm_format(
3132e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        database_pb.identity_binding().identity_public_key());
3142e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
315566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  if (database_pb.identity_key().has_identity_credential()) {
316566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    result->set_certificate(database_pb.identity_key().identity_credential());
317566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  }
318566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  if (database_pb.has_pcr0_quote()) {
319566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    *result->mutable_pcr0_quote() = database_pb.pcr0_quote();
320566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  }
321566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  if (database_pb.has_pcr1_quote()) {
322566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    *result->mutable_pcr1_quote() = database_pb.pcr1_quote();
323566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  }
324566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn}
325566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn
3262e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahnvoid AttestationService::ActivateAttestationKey(
3272e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    const ActivateAttestationKeyRequest& request,
3282e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    const ActivateAttestationKeyCallback& callback) {
3292e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  auto result = std::make_shared<ActivateAttestationKeyReply>();
3302e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  base::Closure task = base::Bind(
3312e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      &AttestationService::ActivateAttestationKeyTask,
3322e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      base::Unretained(this),
3332e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      request,
3342e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      result);
3352e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  base::Closure reply = base::Bind(
3362e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      &AttestationService::TaskRelayCallback<ActivateAttestationKeyReply>,
3372e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      GetWeakPtr(),
3382e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      callback,
3392e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      result);
3402e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
3412e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn}
3422e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
3432e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahnvoid AttestationService::ActivateAttestationKeyTask(
3442e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    const ActivateAttestationKeyRequest& request,
3452e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    const std::shared_ptr<ActivateAttestationKeyReply>& result) {
3462e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  if (request.key_type() != KEY_TYPE_RSA) {
3472e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    result->set_status(STATUS_INVALID_PARAMETER);
3482e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    return;
3492e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
3502e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  std::string certificate;
3512e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  auto database_pb = database_->GetProtobuf();
3522e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  if (!tpm_utility_->ActivateIdentity(
3532e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      database_pb.delegate().blob(),
3542e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      database_pb.delegate().secret(),
3552e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      database_pb.identity_key().identity_key_blob(),
3562e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      request.encrypted_certificate().asym_ca_contents(),
3572e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      request.encrypted_certificate().sym_ca_attestation(),
3582e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      &certificate)) {
3592e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    LOG(ERROR) << __func__ << ": Failed to activate identity.";
3602e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
3612e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    return;
3622e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
3632e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  if (request.save_certificate()) {
3642e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    database_->GetMutableProtobuf()->mutable_identity_key()->
3652e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        set_identity_credential(certificate);
3662e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    if (!database_->SaveChanges()) {
3672e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      LOG(ERROR) << __func__ << ": Failed to persist database changes.";
3682e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
3692e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    }
3702e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
3712e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  result->set_certificate(certificate);
3722e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn}
3732e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
37462c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahnvoid AttestationService::CreateCertifiableKey(
37562c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    const CreateCertifiableKeyRequest& request,
37662c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    const CreateCertifiableKeyCallback& callback) {
37762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  auto result = std::make_shared<CreateCertifiableKeyReply>();
37862c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  base::Closure task = base::Bind(
37962c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      &AttestationService::CreateCertifiableKeyTask,
38062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      base::Unretained(this),
38162c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      request,
38262c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      result);
38362c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  base::Closure reply = base::Bind(
38462c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      &AttestationService::TaskRelayCallback<CreateCertifiableKeyReply>,
38562c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      GetWeakPtr(),
38662c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      callback,
38762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      result);
38862c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
38962c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn}
39062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn
39162c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahnvoid AttestationService::CreateCertifiableKeyTask(
39262c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    const CreateCertifiableKeyRequest& request,
39362c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    const std::shared_ptr<CreateCertifiableKeyReply>& result) {
39462c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  CertifiedKey key;
39562c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  if (!CreateKey(request.username(), request.key_label(), request.key_type(),
39662c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn                 request.key_usage(), &key)) {
39762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
39862c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    return;
39962c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  }
40062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  std::string public_key_info;
40162c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  if (!GetSubjectPublicKeyInfo(key.key_type(), key.public_key(),
40262c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn                               &public_key_info)) {
40362c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    LOG(ERROR) << __func__ << ": Bad public key.";
40462c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
40562c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    return;
40662c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  }
40762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  result->set_public_key(public_key_info);
40862c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  result->set_certify_info(key.certified_key_info());
40962c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  result->set_certify_info_signature(key.certified_key_proof());
41062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn}
41162c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn
412bc0c74963418442991072b2c87baec839eec9c20Darren Krahnvoid AttestationService::Decrypt(const DecryptRequest& request,
413bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                                 const DecryptCallback& callback) {
414bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  auto result = std::make_shared<DecryptReply>();
415bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  base::Closure task = base::Bind(
416bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      &AttestationService::DecryptTask,
417bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      base::Unretained(this),
418bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      request,
419bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      result);
420bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  base::Closure reply = base::Bind(
421bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      &AttestationService::TaskRelayCallback<DecryptReply>,
422bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      GetWeakPtr(),
423bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      callback,
424bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      result);
425bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
426bc0c74963418442991072b2c87baec839eec9c20Darren Krahn}
427bc0c74963418442991072b2c87baec839eec9c20Darren Krahn
428bc0c74963418442991072b2c87baec839eec9c20Darren Krahnvoid AttestationService::DecryptTask(
429bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    const DecryptRequest& request,
430bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    const std::shared_ptr<DecryptReply>& result) {
431bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  CertifiedKey key;
432bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
433bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    result->set_status(STATUS_INVALID_PARAMETER);
434bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    return;
435bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  }
436bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  std::string data;
437bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  if (!tpm_utility_->Unbind(key.key_blob(), request.encrypted_data(), &data)) {
438bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
439bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    return;
440bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  }
441bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  result->set_decrypted_data(data);
442bc0c74963418442991072b2c87baec839eec9c20Darren Krahn}
443bc0c74963418442991072b2c87baec839eec9c20Darren Krahn
444ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahnvoid AttestationService::Sign(const SignRequest& request,
445ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                              const SignCallback& callback) {
446ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  auto result = std::make_shared<SignReply>();
447ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  base::Closure task = base::Bind(
448ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      &AttestationService::SignTask,
449ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      base::Unretained(this),
450ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      request,
451ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      result);
452ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  base::Closure reply = base::Bind(
453ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      &AttestationService::TaskRelayCallback<SignReply>,
454ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      GetWeakPtr(),
455ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      callback,
456ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      result);
457ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
458ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn}
459ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn
460ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahnvoid AttestationService::SignTask(const SignRequest& request,
461ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                                  const std::shared_ptr<SignReply>& result) {
462ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  CertifiedKey key;
463ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
464ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    result->set_status(STATUS_INVALID_PARAMETER);
465ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    return;
466ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  }
467ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  std::string signature;
468ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  if (!tpm_utility_->Sign(key.key_blob(), request.data_to_sign(), &signature)) {
469ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
470ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    return;
471ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  }
472ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  result->set_signature(signature);
473ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn}
474ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn
475594849c7cf872d055575277b930f4f596bef1988Darren Krahnvoid AttestationService::RegisterKeyWithChapsToken(
476594849c7cf872d055575277b930f4f596bef1988Darren Krahn    const RegisterKeyWithChapsTokenRequest& request,
477594849c7cf872d055575277b930f4f596bef1988Darren Krahn    const RegisterKeyWithChapsTokenCallback& callback) {
478594849c7cf872d055575277b930f4f596bef1988Darren Krahn  auto result = std::make_shared<RegisterKeyWithChapsTokenReply>();
479594849c7cf872d055575277b930f4f596bef1988Darren Krahn  base::Closure task = base::Bind(
480594849c7cf872d055575277b930f4f596bef1988Darren Krahn      &AttestationService::RegisterKeyWithChapsTokenTask,
481594849c7cf872d055575277b930f4f596bef1988Darren Krahn      base::Unretained(this),
482594849c7cf872d055575277b930f4f596bef1988Darren Krahn      request,
483594849c7cf872d055575277b930f4f596bef1988Darren Krahn      result);
484594849c7cf872d055575277b930f4f596bef1988Darren Krahn  base::Closure reply = base::Bind(
485594849c7cf872d055575277b930f4f596bef1988Darren Krahn      &AttestationService::TaskRelayCallback<RegisterKeyWithChapsTokenReply>,
486594849c7cf872d055575277b930f4f596bef1988Darren Krahn      GetWeakPtr(),
487594849c7cf872d055575277b930f4f596bef1988Darren Krahn      callback,
488594849c7cf872d055575277b930f4f596bef1988Darren Krahn      result);
489594849c7cf872d055575277b930f4f596bef1988Darren Krahn  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
490594849c7cf872d055575277b930f4f596bef1988Darren Krahn}
491594849c7cf872d055575277b930f4f596bef1988Darren Krahn
492594849c7cf872d055575277b930f4f596bef1988Darren Krahnvoid AttestationService::RegisterKeyWithChapsTokenTask(
493594849c7cf872d055575277b930f4f596bef1988Darren Krahn    const RegisterKeyWithChapsTokenRequest& request,
494594849c7cf872d055575277b930f4f596bef1988Darren Krahn    const std::shared_ptr<RegisterKeyWithChapsTokenReply>& result) {
495594849c7cf872d055575277b930f4f596bef1988Darren Krahn  CertifiedKey key;
496594849c7cf872d055575277b930f4f596bef1988Darren Krahn  if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
497594849c7cf872d055575277b930f4f596bef1988Darren Krahn    result->set_status(STATUS_INVALID_PARAMETER);
498594849c7cf872d055575277b930f4f596bef1988Darren Krahn    return;
499594849c7cf872d055575277b930f4f596bef1988Darren Krahn  }
500594849c7cf872d055575277b930f4f596bef1988Darren Krahn  if (!key_store_->Register(request.username(), request.key_label(),
501594849c7cf872d055575277b930f4f596bef1988Darren Krahn                            key.key_type(), key.key_usage(), key.key_blob(),
502594849c7cf872d055575277b930f4f596bef1988Darren Krahn                            key.public_key(), key.certified_key_credential())) {
503594849c7cf872d055575277b930f4f596bef1988Darren Krahn    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
504594849c7cf872d055575277b930f4f596bef1988Darren Krahn    return;
505594849c7cf872d055575277b930f4f596bef1988Darren Krahn  }
506594849c7cf872d055575277b930f4f596bef1988Darren Krahn  if (key.has_intermediate_ca_cert() &&
507594849c7cf872d055575277b930f4f596bef1988Darren Krahn      !key_store_->RegisterCertificate(request.username(),
508594849c7cf872d055575277b930f4f596bef1988Darren Krahn                                       key.intermediate_ca_cert())) {
509594849c7cf872d055575277b930f4f596bef1988Darren Krahn    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
510594849c7cf872d055575277b930f4f596bef1988Darren Krahn    return;
511594849c7cf872d055575277b930f4f596bef1988Darren Krahn  }
512594849c7cf872d055575277b930f4f596bef1988Darren Krahn  for (int i = 0; i < key.additional_intermediate_ca_cert_size(); ++i) {
513594849c7cf872d055575277b930f4f596bef1988Darren Krahn    if (!key_store_->RegisterCertificate(
514594849c7cf872d055575277b930f4f596bef1988Darren Krahn            request.username(),
515594849c7cf872d055575277b930f4f596bef1988Darren Krahn            key.additional_intermediate_ca_cert(i))) {
516594849c7cf872d055575277b930f4f596bef1988Darren Krahn      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
517594849c7cf872d055575277b930f4f596bef1988Darren Krahn      return;
518594849c7cf872d055575277b930f4f596bef1988Darren Krahn    }
519594849c7cf872d055575277b930f4f596bef1988Darren Krahn  }
520594849c7cf872d055575277b930f4f596bef1988Darren Krahn  DeleteKey(request.username(), request.key_label());
521594849c7cf872d055575277b930f4f596bef1988Darren Krahn}
522594849c7cf872d055575277b930f4f596bef1988Darren Krahn
523d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnbool AttestationService::IsPreparedForEnrollment() {
524d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!tpm_utility_->IsTpmReady()) {
525d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
526d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
527d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  auto database_pb = database_->GetProtobuf();
528d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!database_pb.has_credentials()) {
529d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
530d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
531d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return (database_pb.credentials().has_endorsement_credential() ||
532d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn          database_pb.credentials()
533d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn              .has_default_encrypted_endorsement_credential());
534d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
535d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
536d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnbool AttestationService::IsEnrolled() {
537d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  auto database_pb = database_->GetProtobuf();
538d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return database_pb.has_identity_key() &&
539d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn         database_pb.identity_key().has_identity_credential();
540d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
541d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
542d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnbool AttestationService::CreateEnrollRequest(std::string* enroll_request) {
543d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!IsPreparedForEnrollment()) {
544d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << __func__ << ": Enrollment is not possible, attestation data "
545d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn               << "does not exist.";
546d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
547d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
548d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  auto database_pb = database_->GetProtobuf();
549d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  AttestationEnrollmentRequest request_pb;
550d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  *request_pb.mutable_encrypted_endorsement_credential() =
551d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      database_pb.credentials().default_encrypted_endorsement_credential();
552d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  request_pb.set_identity_public_key(
553d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      database_pb.identity_binding().identity_public_key());
554d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  *request_pb.mutable_pcr0_quote() = database_pb.pcr0_quote();
555d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  *request_pb.mutable_pcr1_quote() = database_pb.pcr1_quote();
556d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!request_pb.SerializeToString(enroll_request)) {
557d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
558d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
559d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
560d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return true;
561d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
562d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
563d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnbool AttestationService::FinishEnroll(const std::string& enroll_response,
564d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                      std::string* server_error) {
565d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!tpm_utility_->IsTpmReady()) {
566d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
567d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
568d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  AttestationEnrollmentResponse response_pb;
569d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!response_pb.ParseFromString(enroll_response)) {
570d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << __func__ << ": Failed to parse response from CA.";
571d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
572d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
573d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (response_pb.status() != OK) {
574d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    *server_error = response_pb.detail();
575d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << __func__ << ": Error received from CA: "
576d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn               << response_pb.detail();
577d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
578d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
579d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string credential;
580d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  auto database_pb = database_->GetProtobuf();
581d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!tpm_utility_->ActivateIdentity(
582d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      database_pb.delegate().blob(),
583d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      database_pb.delegate().secret(),
584d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      database_pb.identity_key().identity_key_blob(),
585d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      response_pb.encrypted_identity_credential().asym_ca_contents(),
586d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      response_pb.encrypted_identity_credential().sym_ca_attestation(),
587d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      &credential)) {
588d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << __func__ << ": Failed to activate identity.";
589d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
590d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
591d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  database_->GetMutableProtobuf()->mutable_identity_key()->
592d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      set_identity_credential(credential);
593d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!database_->SaveChanges()) {
594d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << __func__ << ": Failed to persist database changes.";
595d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
596d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
597d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  LOG(INFO) << "Attestation: Enrollment complete.";
598d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return true;
599d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
600d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
601d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnbool AttestationService::CreateCertificateRequest(
602d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    const std::string& username,
60362c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    const CertifiedKey& key,
604d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    CertificateProfile profile,
605d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    const std::string& origin,
606d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    std::string* certificate_request,
607d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    std::string* message_id) {
608d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!tpm_utility_->IsTpmReady()) {
609d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
610d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
611d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!IsEnrolled()) {
612d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << __func__ << ": Device is not enrolled for attestation.";
613d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
614d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
615d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  AttestationCertificateRequest request_pb;
616d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!crypto_utility_->GetRandom(kNonceSize, message_id)) {
617d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << __func__ << ": GetRandom(message_id) failed.";
618d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
619d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
620d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  request_pb.set_message_id(*message_id);
621d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  auto database_pb = database_->GetProtobuf();
622d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  request_pb.set_identity_credential(
623d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      database_pb.identity_key().identity_credential());
624d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  request_pb.set_profile(profile);
625d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!origin.empty() &&
626d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      (profile == CONTENT_PROTECTION_CERTIFICATE_WITH_STABLE_ID)) {
627d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    request_pb.set_origin(origin);
628d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    request_pb.set_temporal_index(ChooseTemporalIndex(username, origin));
629d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
63008d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn  request_pb.set_certified_public_key(key.public_key_tpm_format());
63108d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn  request_pb.set_certified_key_info(key.certified_key_info());
63208d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn  request_pb.set_certified_key_proof(key.certified_key_proof());
633d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!request_pb.SerializeToString(certificate_request)) {
634d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
635d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
636d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
637d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return true;
638d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
639d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
640d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnbool AttestationService::FinishCertificateRequest(
641d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    const std::string& certificate_response,
642d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    const std::string& username,
643d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    const std::string& key_label,
644d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    const std::string& message_id,
64562c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    CertifiedKey* key,
646d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    std::string* certificate_chain,
647d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    std::string* server_error) {
648d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!tpm_utility_->IsTpmReady()) {
649d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
650d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
651d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  AttestationCertificateResponse response_pb;
652d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!response_pb.ParseFromString(certificate_response)) {
653d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << __func__ << ": Failed to parse response from Privacy CA.";
654d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
655d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
656d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (response_pb.status() != OK) {
657d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    *server_error = response_pb.detail();
658d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << __func__ << ": Error received from Privacy CA: "
659d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn               << response_pb.detail();
660d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
661d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
662d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (message_id != response_pb.message_id()) {
663d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << __func__ << ": Message ID mismatch.";
664d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
665d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
666d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
667d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  // Finish populating the CertifiedKey protobuf and store it.
66862c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  key->set_certified_key_credential(response_pb.certified_key_credential());
66962c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  key->set_intermediate_ca_cert(response_pb.intermediate_ca_cert());
67062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  key->mutable_additional_intermediate_ca_cert()->MergeFrom(
671d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      response_pb.additional_intermediate_ca_cert());
67262c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  if (!SaveKey(username, key_label, *key)) {
673d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
674d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
675d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  LOG(INFO) << "Attestation: Certified key credential received and stored.";
67662c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  *certificate_chain = CreatePEMCertificateChain(*key);
677d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return true;
678d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
679d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
680d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnbool AttestationService::SendACARequestAndBlock(ACARequestType request_type,
681d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                                const std::string& request,
682d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                                std::string* reply) {
683e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko  std::shared_ptr<brillo::http::Transport> transport = http_transport_;
684d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!transport) {
685e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko    transport = brillo::http::Transport::CreateDefault();
686d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
687e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko  std::unique_ptr<brillo::http::Response> response = PostBinaryAndBlock(
688d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      GetACAURL(request_type),
689d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      request.data(),
690d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      request.size(),
691e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko      brillo::mime::application::kOctet_stream,
692d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      {},  // headers
693d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      transport,
694d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      nullptr);  // error
695d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!response || !response->IsSuccessful()) {
696d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(ERROR) << "HTTP request to Attestation CA failed.";
697d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
698d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
699d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  *reply = response->ExtractDataAsString();
700d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return true;
701d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
702d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
703d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnbool AttestationService::FindKeyByLabel(const std::string& username,
704d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                        const std::string& key_label,
705d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                        CertifiedKey* key) {
706d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!username.empty()) {
707d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    std::string key_data;
708d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (!key_store_->Read(username, key_label, &key_data)) {
709d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      LOG(INFO) << "Key not found: " << key_label;
710d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      return false;
711d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
712d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (key && !key->ParseFromString(key_data)) {
713d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      LOG(ERROR) << "Failed to parse key: " << key_label;
714d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      return false;
715d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
716d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return true;
717d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
718d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  auto database_pb = database_->GetProtobuf();
719d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  for (int i = 0; i < database_pb.device_keys_size(); ++i) {
720d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (database_pb.device_keys(i).key_name() == key_label) {
721d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      *key = database_pb.device_keys(i);
722d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      return true;
723d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
724d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
725d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  LOG(INFO) << "Key not found: " << key_label;
726d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return false;
727d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
728d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
729d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnbool AttestationService::CreateKey(const std::string& username,
730d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                   const std::string& key_label,
731d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                   KeyType key_type,
73262c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn                                   KeyUsage key_usage,
73362c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn                                   CertifiedKey* key) {
73408d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn  std::string nonce;
73508d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn  if (!crypto_utility_->GetRandom(kNonceSize, &nonce)) {
73608d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn    LOG(ERROR) << __func__ << ": GetRandom(nonce) failed.";
73708d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn    return false;
73808d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn  }
739d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string key_blob;
740d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string public_key;
74108d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn  std::string public_key_tpm_format;
74208d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn  std::string key_info;
74308d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn  std::string proof;
74408d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn  auto database_pb = database_->GetProtobuf();
74508d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn  if (!tpm_utility_->CreateCertifiedKey(
74608d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn      key_type,
74708d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn      key_usage,
74808d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn      database_pb.identity_key().identity_key_blob(),
74908d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn      nonce,
75008d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn      &key_blob,
75108d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn      &public_key,
75208d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn      &public_key_tpm_format,
75308d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn      &key_info,
75408d544a489c1a2608b01ff240bddb26d4a92b277Darren Krahn      &proof)) {
755d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return false;
756d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
75762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  key->set_key_blob(key_blob);
75862c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  key->set_public_key(public_key);
75962c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  key->set_key_name(key_label);
76062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  key->set_public_key_tpm_format(public_key_tpm_format);
76162c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  key->set_certified_key_info(key_info);
76262c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  key->set_certified_key_proof(proof);
76362c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  return SaveKey(username, key_label, *key);
764d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
765d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
766d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnbool AttestationService::SaveKey(const std::string& username,
767d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                 const std::string& key_label,
768d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                 const CertifiedKey& key) {
769d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!username.empty()) {
770d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    std::string key_data;
771d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (!key.SerializeToString(&key_data)) {
772d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
773d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      return false;
774d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
775d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (!key_store_->Write(username, key_label, key_data)) {
776d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      LOG(ERROR) << __func__ << ": Failed to store certified key for user.";
777d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      return false;
778d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
779d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  } else {
780d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (!AddDeviceKey(key_label, key)) {
781d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      LOG(ERROR) << __func__ << ": Failed to store certified key for device.";
782d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      return false;
783d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
784d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
785d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return true;
786d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
787d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
788d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnvoid AttestationService::DeleteKey(const std::string& username,
789d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                   const std::string& key_label) {
790d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!username.empty()) {
791d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    key_store_->Delete(username, key_label);
792d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  } else {
793d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    RemoveDeviceKey(key_label);
794d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
795d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
796d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
797d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnbool AttestationService::AddDeviceKey(const std::string& key_label,
798d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                      const CertifiedKey& key) {
799d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  // If a key by this name already exists, reuse the field.
800d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  auto* database_pb = database_->GetMutableProtobuf();
801d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  bool found = false;
802d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  for (int i = 0; i < database_pb->device_keys_size(); ++i) {
803d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (database_pb->device_keys(i).key_name() == key_label) {
804d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      found = true;
805d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      *database_pb->mutable_device_keys(i) = key;
806d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      break;
807d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
808d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
809d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!found)
810d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    *database_pb->add_device_keys() = key;
811d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return database_->SaveChanges();
812d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
813d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
814d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnvoid AttestationService::RemoveDeviceKey(const std::string& key_label) {
815d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  auto* database_pb = database_->GetMutableProtobuf();
816d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  bool found = false;
817d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  for (int i = 0; i < database_pb->device_keys_size(); ++i) {
818d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (database_pb->device_keys(i).key_name() == key_label) {
819d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      found = true;
820d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      int last = database_pb->device_keys_size() - 1;
821d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      if (i < last) {
822d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn        database_pb->mutable_device_keys()->SwapElements(i, last);
823d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      }
824d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      database_pb->mutable_device_keys()->RemoveLast();
825d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      break;
826d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
827d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
828d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (found) {
829d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (!database_->SaveChanges()) {
830d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      LOG(WARNING) << __func__ << ": Failed to persist key deletion.";
831d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
832d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
833d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
834d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
835d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnstd::string AttestationService::CreatePEMCertificateChain(
836d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    const CertifiedKey& key) {
837d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (key.certified_key_credential().empty()) {
838d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(WARNING) << "Certificate is empty.";
839d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    return std::string();
840d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
841d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string pem = CreatePEMCertificate(key.certified_key_credential());
842d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (!key.intermediate_ca_cert().empty()) {
843d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    pem += "\n";
844d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    pem += CreatePEMCertificate(key.intermediate_ca_cert());
845d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
846d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  for (int i = 0; i < key.additional_intermediate_ca_cert_size(); ++i) {
847d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    pem += "\n";
848d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    pem += CreatePEMCertificate(key.additional_intermediate_ca_cert(i));
849d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
850d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return pem;
851d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
852d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
853d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnstd::string AttestationService::CreatePEMCertificate(
854d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    const std::string& certificate) {
855d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  const char kBeginCertificate[] = "-----BEGIN CERTIFICATE-----\n";
856d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  const char kEndCertificate[] = "-----END CERTIFICATE-----";
857d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
858d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string pem = kBeginCertificate;
859e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko  pem += brillo::data_encoding::Base64EncodeWrapLines(certificate);
860d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  pem += kEndCertificate;
861d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return pem;
862d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
863d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
864d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
865d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnint AttestationService::ChooseTemporalIndex(const std::string& user,
866d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn                                            const std::string& origin) {
867d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string user_hash = crypto::SHA256HashString(user);
868d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string origin_hash = crypto::SHA256HashString(origin);
869d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  int histogram[kNumTemporalValues] = {};
870d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  auto database_pb = database_->GetProtobuf();
871d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  for (int i = 0; i < database_pb.temporal_index_record_size(); ++i) {
872d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    const AttestationDatabase::TemporalIndexRecord& record =
873d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn        database_pb.temporal_index_record(i);
874d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    // Ignore out-of-range index values.
875d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (record.temporal_index() < 0 ||
876d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn        record.temporal_index() >= kNumTemporalValues)
877d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      continue;
878d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (record.origin_hash() == origin_hash) {
879d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      if (record.user_hash() == user_hash) {
880d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn        // We've previously chosen this index for this user, reuse it.
881d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn        return record.temporal_index();
882d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      } else {
883d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn        // We've previously chosen this index for another user.
884d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn        ++histogram[record.temporal_index()];
885d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      }
886d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    }
887d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
888d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  int least_used_index = 0;
889d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  for (int i = 1; i < kNumTemporalValues; ++i) {
890d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    if (histogram[i] < histogram[least_used_index])
891d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      least_used_index = i;
892d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
893d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  if (histogram[least_used_index] > 0) {
894d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    LOG(WARNING) << "Unique origin-specific identifiers have been exhausted.";
895d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
896d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  // Record our choice for later reference.
897d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  AttestationDatabase::TemporalIndexRecord* new_record =
898d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      database_pb.add_temporal_index_record();
899d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  new_record->set_origin_hash(origin_hash);
900d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  new_record->set_user_hash(user_hash);
901d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  new_record->set_temporal_index(least_used_index);
902d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  database_->SaveChanges();
903d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return least_used_index;
904d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
905d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
906d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnstd::string AttestationService::GetACAURL(ACARequestType request_type) const {
907d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  std::string url = attestation_ca_origin_;
908d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  switch (request_type) {
909d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    case kEnroll:
910d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      url += "/enroll";
911d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      break;
912d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    case kGetCertificate:
913d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      url += "/sign";
914d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      break;
915d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn    default:
916d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn      NOTREACHED();
917d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  }
918d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return url;
919d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn}
920d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn
9216222defa52eb13c0d90673f642f2647f7753478bDarren Krahnbool AttestationService::GetSubjectPublicKeyInfo(
9226222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    KeyType key_type,
9236222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    const std::string& public_key,
9246222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    std::string* public_key_info) const {
9256222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  // Only RSA is supported currently.
9266222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  if (key_type != KEY_TYPE_RSA) {
9276222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    return false;
9286222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  }
9296222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  return crypto_utility_->GetRSASubjectPublicKeyInfo(public_key,
9306222defa52eb13c0d90673f642f2647f7753478bDarren Krahn                                                     public_key_info);
9316222defa52eb13c0d90673f642f2647f7753478bDarren Krahn}
9326222defa52eb13c0d90673f642f2647f7753478bDarren Krahn
933d66389850c33614ffbbbbc3f768621182fd853baDarren Krahnbase::WeakPtr<AttestationService> AttestationService::GetWeakPtr() {
934d66389850c33614ffbbbbc3f768621182fd853baDarren Krahn  return weak_factory_.GetWeakPtr();
9356bead48129845a2bc0d6ff347f3d7e232004d59Nam T. Nguyen}
9366bead48129845a2bc0d6ff347f3d7e232004d59Nam T. Nguyen
937ab0cddda9971f97781fc9f6cbc76095ba7542abfAlex Vakulenko}  // namespace attestation
938