• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef ATTESTATION_SERVER_ATTESTATION_SERVICE_H_
18 #define ATTESTATION_SERVER_ATTESTATION_SERVICE_H_
19 
20 #include "attestation/common/attestation_interface.h"
21 
22 #include <memory>
23 #include <string>
24 
25 #include <base/callback.h>
26 #include <base/macros.h>
27 #include <base/memory/weak_ptr.h>
28 #include <base/threading/thread.h>
29 #include <brillo/bind_lambda.h>
30 #include <brillo/http/http_transport.h>
31 
32 #include "attestation/common/crypto_utility.h"
33 #include "attestation/common/crypto_utility_impl.h"
34 #include "attestation/common/tpm_utility.h"
35 #include "attestation/common/tpm_utility_v1.h"
36 #include "attestation/server/database.h"
37 #include "attestation/server/database_impl.h"
38 #include "attestation/server/key_store.h"
39 #include "attestation/server/pkcs11_key_store.h"
40 
41 namespace attestation {
42 
43 // An implementation of AttestationInterface for the core attestation service.
44 // Access to TPM, network and local file-system resources occurs asynchronously
45 // with the exception of Initialize(). All methods must be called on the same
46 // thread that originally called Initialize().
47 // Usage:
48 //   std::unique_ptr<AttestationInterface> attestation =
49 //       new AttestationService();
50 //   CHECK(attestation->Initialize());
51 //   attestation->CreateGoogleAttestedKey(...);
52 //
53 // THREADING NOTES:
54 // This class runs a worker thread and delegates all calls to it. This keeps the
55 // public methods non-blocking while allowing complex implementation details
56 // with dependencies on the TPM, network, and filesystem to be coded in a more
57 // readable way. It also serves to serialize method execution which reduces
58 // complexity with TPM state.
59 //
60 // Tasks that run on the worker thread are bound with base::Unretained which is
61 // safe because the thread is owned by this class (so it is guaranteed not to
62 // process a task after destruction). Weak pointers are used to post replies
63 // back to the main thread.
64 class AttestationService : public AttestationInterface {
65  public:
66   AttestationService();
67   ~AttestationService() override = default;
68 
69   // AttestationInterface methods.
70   bool Initialize() override;
71   void CreateGoogleAttestedKey(
72       const CreateGoogleAttestedKeyRequest& request,
73       const CreateGoogleAttestedKeyCallback& callback) override;
74   void GetKeyInfo(const GetKeyInfoRequest& request,
75                   const GetKeyInfoCallback& callback) override;
76   void GetEndorsementInfo(const GetEndorsementInfoRequest& request,
77                           const GetEndorsementInfoCallback& callback) override;
78   void GetAttestationKeyInfo(
79       const GetAttestationKeyInfoRequest& request,
80       const GetAttestationKeyInfoCallback& callback) override;
81   void ActivateAttestationKey(
82       const ActivateAttestationKeyRequest& request,
83       const ActivateAttestationKeyCallback& callback) override;
84   void CreateCertifiableKey(
85       const CreateCertifiableKeyRequest& request,
86       const CreateCertifiableKeyCallback& callback) override;
87   void Decrypt(const DecryptRequest& request,
88                const DecryptCallback& callback) override;
89   void Sign(const SignRequest& request, const SignCallback& callback) override;
90   void RegisterKeyWithChapsToken(
91       const RegisterKeyWithChapsTokenRequest& request,
92       const RegisterKeyWithChapsTokenCallback& callback) override;
93 
94   // Mutators useful for testing.
set_crypto_utility(CryptoUtility * crypto_utility)95   void set_crypto_utility(CryptoUtility* crypto_utility) {
96     crypto_utility_ = crypto_utility;
97   }
98 
set_database(Database * database)99   void set_database(Database* database) {
100     database_ = database;
101   }
102 
set_http_transport(const std::shared_ptr<brillo::http::Transport> & transport)103   void set_http_transport(
104       const std::shared_ptr<brillo::http::Transport>& transport) {
105     http_transport_ = transport;
106   }
107 
set_key_store(KeyStore * key_store)108   void set_key_store(KeyStore* key_store) {
109     key_store_ = key_store;
110   }
111 
set_tpm_utility(TpmUtility * tpm_utility)112   void set_tpm_utility(TpmUtility* tpm_utility) {
113     tpm_utility_ = tpm_utility;
114   }
115 
116   // So tests don't need to duplicate URL decisions.
attestation_ca_origin()117   const std::string& attestation_ca_origin() {
118     return attestation_ca_origin_;
119   }
120 
121  private:
122   enum ACARequestType {
123     kEnroll,          // Enrolls a device, certifying an identity key.
124     kGetCertificate,  // Issues a certificate for a TPM-backed key.
125   };
126 
127   // A relay callback which allows the use of weak pointer semantics for a reply
128   // to TaskRunner::PostTaskAndReply.
129   template<typename ReplyProtobufType>
TaskRelayCallback(const base::Callback<void (const ReplyProtobufType &)> callback,const std::shared_ptr<ReplyProtobufType> & reply)130   void TaskRelayCallback(
131       const base::Callback<void(const ReplyProtobufType&)> callback,
132       const std::shared_ptr<ReplyProtobufType>& reply) {
133     callback.Run(*reply);
134   }
135 
136   // A blocking implementation of CreateGoogleAttestedKey appropriate to run on
137   // the worker thread.
138   void CreateGoogleAttestedKeyTask(
139       const CreateGoogleAttestedKeyRequest& request,
140       const std::shared_ptr<CreateGoogleAttestedKeyReply>& result);
141 
142   // A blocking implementation of GetKeyInfo.
143   void GetKeyInfoTask(
144       const GetKeyInfoRequest& request,
145       const std::shared_ptr<GetKeyInfoReply>& result);
146 
147   // A blocking implementation of GetEndorsementInfo.
148   void GetEndorsementInfoTask(
149       const GetEndorsementInfoRequest& request,
150       const std::shared_ptr<GetEndorsementInfoReply>& result);
151 
152   // A blocking implementation of GetAttestationKeyInfo.
153   void GetAttestationKeyInfoTask(
154       const GetAttestationKeyInfoRequest& request,
155       const std::shared_ptr<GetAttestationKeyInfoReply>& result);
156 
157   // A blocking implementation of ActivateAttestationKey.
158   void ActivateAttestationKeyTask(
159       const ActivateAttestationKeyRequest& request,
160       const std::shared_ptr<ActivateAttestationKeyReply>& result);
161 
162   // A blocking implementation of CreateCertifiableKey.
163   void CreateCertifiableKeyTask(
164       const CreateCertifiableKeyRequest& request,
165       const std::shared_ptr<CreateCertifiableKeyReply>& result);
166 
167   // A blocking implementation of Decrypt.
168   void DecryptTask(const DecryptRequest& request,
169                    const std::shared_ptr<DecryptReply>& result);
170 
171   // A blocking implementation of Sign.
172   void SignTask(const SignRequest& request,
173                 const std::shared_ptr<SignReply>& result);
174 
175   // A synchronous implementation of RegisterKeyWithChapsToken.
176   void RegisterKeyWithChapsTokenTask(
177       const RegisterKeyWithChapsTokenRequest& request,
178       const std::shared_ptr<RegisterKeyWithChapsTokenReply>& result);
179 
180   // Returns true iff all information required for enrollment with the Google
181   // Attestation CA is available.
182   bool IsPreparedForEnrollment();
183 
184   // Returns true iff enrollment with the Google Attestation CA has been
185   // completed.
186   bool IsEnrolled();
187 
188   // Creates an enrollment request compatible with the Google Attestation CA.
189   // Returns true on success.
190   bool CreateEnrollRequest(std::string* enroll_request);
191 
192   // Finishes enrollment given an |enroll_response| from the Google Attestation
193   // CA. Returns true on success. On failure, returns false and sets
194   // |server_error| to the error string from the CA.
195   bool FinishEnroll(const std::string& enroll_response,
196                     std::string* server_error);
197 
198   // Creates a |certificate_request| compatible with the Google Attestation CA
199   // for the given |key|, according to the given |profile|, |username| and
200   // |origin|.
201   bool CreateCertificateRequest(const std::string& username,
202                                 const CertifiedKey& key,
203                                 CertificateProfile profile,
204                                 const std::string& origin,
205                                 std::string* certificate_request,
206                                 std::string* message_id);
207 
208   // Finishes a certificate request by decoding the |certificate_response| to
209   // recover the |certificate_chain| and storing it in association with the
210   // |key| identified by |username| and |key_label|. Returns true on success. On
211   // failure, returns false and sets |server_error| to the error string from the
212   // CA.
213   bool FinishCertificateRequest(const std::string& certificate_response,
214                                 const std::string& username,
215                                 const std::string& key_label,
216                                 const std::string& message_id,
217                                 CertifiedKey* key,
218                                 std::string* certificate_chain,
219                                 std::string* server_error);
220 
221   // Sends a |request_type| |request| to the Google Attestation CA and waits for
222   // the |reply|. Returns true on success.
223   bool SendACARequestAndBlock(ACARequestType request_type,
224                               const std::string& request,
225                               std::string* reply);
226 
227   // Creates, certifies, and saves a new |key| for |username| with the given
228   // |key_label|, |key_type|, and |key_usage|. Returns true on success.
229   bool CreateKey(const std::string& username,
230                  const std::string& key_label,
231                  KeyType key_type,
232                  KeyUsage key_usage,
233                  CertifiedKey* key);
234 
235   // Finds the |key| associated with |username| and |key_label|. Returns false
236   // if such a key does not exist.
237   bool FindKeyByLabel(const std::string& username,
238                       const std::string& key_label,
239                       CertifiedKey* key);
240 
241   // Saves the |key| associated with |username| and |key_label|. Returns true on
242   // success.
243   bool SaveKey(const std::string& username,
244                const std::string& key_label,
245                const CertifiedKey& key);
246 
247   // Deletes the key associated with |username| and |key_label|.
248   void DeleteKey(const std::string& username,
249                  const std::string& key_label);
250 
251   // Adds named device-wide key to the attestation database.
252   bool AddDeviceKey(const std::string& key_label, const CertifiedKey& key);
253 
254   // Removes a device-wide key from the attestation database.
255   void RemoveDeviceKey(const std::string& key_label);
256 
257   // Creates a PEM certificate chain from the credential fields of a |key|.
258   std::string CreatePEMCertificateChain(const CertifiedKey& key);
259 
260   // Creates a certificate in PEM format from a DER encoded X.509 certificate.
261   std::string CreatePEMCertificate(const std::string& certificate);
262 
263   // Chooses a temporal index which will be used by the ACA to create a
264   // certificate.  This decision factors in the currently signed-in |user| and
265   // the |origin| of the certificate request.  The strategy is to find an index
266   // which has not already been used by another user for the same origin.
267   int ChooseTemporalIndex(const std::string& user, const std::string& origin);
268 
269   // Creates a Google Attestation CA URL for the given |request_type|.
270   std::string GetACAURL(ACARequestType request_type) const;
271 
272   // Creates a X.509/DER SubjectPublicKeyInfo for the given |key_type| and
273   // |public_key|. On success returns true and provides |public_key_info|.
274   bool GetSubjectPublicKeyInfo(KeyType key_type,
275                                const std::string& public_key,
276                                std::string* public_key_info) const;
277 
278   base::WeakPtr<AttestationService> GetWeakPtr();
279 
280 
281   const std::string attestation_ca_origin_;
282 
283   // Other than initialization and destruction, these are used only by the
284   // worker thread.
285   CryptoUtility* crypto_utility_{nullptr};
286   Database* database_{nullptr};
287   std::shared_ptr<brillo::http::Transport> http_transport_;
288   KeyStore* key_store_{nullptr};
289   TpmUtility* tpm_utility_{nullptr};
290 
291   // Default implementations for the above interfaces. These will be setup
292   // during Initialize() if the corresponding interface has not been set with a
293   // mutator.
294   std::unique_ptr<CryptoUtilityImpl> default_crypto_utility_;
295   std::unique_ptr<DatabaseImpl> default_database_;
296   std::unique_ptr<Pkcs11KeyStore> default_key_store_;
297   std::unique_ptr<chaps::TokenManagerClient> pkcs11_token_manager_;
298   std::unique_ptr<TpmUtilityV1> default_tpm_utility_;
299 
300   // All work is done in the background. This serves to serialize requests and
301   // allow synchronous implementation of complex methods. This is intentionally
302   // declared after the thread-owned members.
303   std::unique_ptr<base::Thread> worker_thread_;
304 
305   // Declared last so any weak pointers are destroyed first.
306   base::WeakPtrFactory<AttestationService> weak_factory_;
307 
308   DISALLOW_COPY_AND_ASSIGN(AttestationService);
309 };
310 
311 }  // namespace attestation
312 
313 #endif  // ATTESTATION_SERVER_ATTESTATION_SERVICE_H_
314