// // Copyright (C) 2015 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef ATTESTATION_SERVER_ATTESTATION_SERVICE_H_ #define ATTESTATION_SERVER_ATTESTATION_SERVICE_H_ #include "attestation/common/attestation_interface.h" #include <memory> #include <string> #include <base/callback.h> #include <base/macros.h> #include <base/memory/weak_ptr.h> #include <base/threading/thread.h> #include <brillo/bind_lambda.h> #include <brillo/http/http_transport.h> #include "attestation/common/crypto_utility.h" #include "attestation/common/crypto_utility_impl.h" #include "attestation/common/tpm_utility.h" #include "attestation/common/tpm_utility_v1.h" #include "attestation/server/database.h" #include "attestation/server/database_impl.h" #include "attestation/server/key_store.h" #include "attestation/server/pkcs11_key_store.h" namespace attestation { // An implementation of AttestationInterface for the core attestation service. // Access to TPM, network and local file-system resources occurs asynchronously // with the exception of Initialize(). All methods must be called on the same // thread that originally called Initialize(). // Usage: // std::unique_ptr<AttestationInterface> attestation = // new AttestationService(); // CHECK(attestation->Initialize()); // attestation->CreateGoogleAttestedKey(...); // // THREADING NOTES: // This class runs a worker thread and delegates all calls to it. This keeps the // public methods non-blocking while allowing complex implementation details // with dependencies on the TPM, network, and filesystem to be coded in a more // readable way. It also serves to serialize method execution which reduces // complexity with TPM state. // // Tasks that run on the worker thread are bound with base::Unretained which is // safe because the thread is owned by this class (so it is guaranteed not to // process a task after destruction). Weak pointers are used to post replies // back to the main thread. class AttestationService : public AttestationInterface { public: AttestationService(); ~AttestationService() override = default; // AttestationInterface methods. bool Initialize() override; void CreateGoogleAttestedKey( const CreateGoogleAttestedKeyRequest& request, const CreateGoogleAttestedKeyCallback& callback) override; void GetKeyInfo(const GetKeyInfoRequest& request, const GetKeyInfoCallback& callback) override; void GetEndorsementInfo(const GetEndorsementInfoRequest& request, const GetEndorsementInfoCallback& callback) override; void GetAttestationKeyInfo( const GetAttestationKeyInfoRequest& request, const GetAttestationKeyInfoCallback& callback) override; void ActivateAttestationKey( const ActivateAttestationKeyRequest& request, const ActivateAttestationKeyCallback& callback) override; void CreateCertifiableKey( const CreateCertifiableKeyRequest& request, const CreateCertifiableKeyCallback& callback) override; void Decrypt(const DecryptRequest& request, const DecryptCallback& callback) override; void Sign(const SignRequest& request, const SignCallback& callback) override; void RegisterKeyWithChapsToken( const RegisterKeyWithChapsTokenRequest& request, const RegisterKeyWithChapsTokenCallback& callback) override; // Mutators useful for testing. void set_crypto_utility(CryptoUtility* crypto_utility) { crypto_utility_ = crypto_utility; } void set_database(Database* database) { database_ = database; } void set_http_transport( const std::shared_ptr<brillo::http::Transport>& transport) { http_transport_ = transport; } void set_key_store(KeyStore* key_store) { key_store_ = key_store; } void set_tpm_utility(TpmUtility* tpm_utility) { tpm_utility_ = tpm_utility; } // So tests don't need to duplicate URL decisions. const std::string& attestation_ca_origin() { return attestation_ca_origin_; } private: enum ACARequestType { kEnroll, // Enrolls a device, certifying an identity key. kGetCertificate, // Issues a certificate for a TPM-backed key. }; // A relay callback which allows the use of weak pointer semantics for a reply // to TaskRunner::PostTaskAndReply. template <typename ReplyProtobufType> void TaskRelayCallback( const base::Callback<void(const ReplyProtobufType&)> callback, const std::shared_ptr<ReplyProtobufType>& reply) { callback.Run(*reply); } // A blocking implementation of CreateGoogleAttestedKey appropriate to run on // the worker thread. void CreateGoogleAttestedKeyTask( const CreateGoogleAttestedKeyRequest& request, const std::shared_ptr<CreateGoogleAttestedKeyReply>& result); // A blocking implementation of GetKeyInfo. void GetKeyInfoTask(const GetKeyInfoRequest& request, const std::shared_ptr<GetKeyInfoReply>& result); // A blocking implementation of GetEndorsementInfo. void GetEndorsementInfoTask( const GetEndorsementInfoRequest& request, const std::shared_ptr<GetEndorsementInfoReply>& result); // A blocking implementation of GetAttestationKeyInfo. void GetAttestationKeyInfoTask( const GetAttestationKeyInfoRequest& request, const std::shared_ptr<GetAttestationKeyInfoReply>& result); // A blocking implementation of ActivateAttestationKey. void ActivateAttestationKeyTask( const ActivateAttestationKeyRequest& request, const std::shared_ptr<ActivateAttestationKeyReply>& result); // A blocking implementation of CreateCertifiableKey. void CreateCertifiableKeyTask( const CreateCertifiableKeyRequest& request, const std::shared_ptr<CreateCertifiableKeyReply>& result); // A blocking implementation of Decrypt. void DecryptTask(const DecryptRequest& request, const std::shared_ptr<DecryptReply>& result); // A blocking implementation of Sign. void SignTask(const SignRequest& request, const std::shared_ptr<SignReply>& result); // A synchronous implementation of RegisterKeyWithChapsToken. void RegisterKeyWithChapsTokenTask( const RegisterKeyWithChapsTokenRequest& request, const std::shared_ptr<RegisterKeyWithChapsTokenReply>& result); // Returns true iff all information required for enrollment with the Google // Attestation CA is available. bool IsPreparedForEnrollment(); // Returns true iff enrollment with the Google Attestation CA has been // completed. bool IsEnrolled(); // Creates an enrollment request compatible with the Google Attestation CA. // Returns true on success. bool CreateEnrollRequest(std::string* enroll_request); // Finishes enrollment given an |enroll_response| from the Google Attestation // CA. Returns true on success. On failure, returns false and sets // |server_error| to the error string from the CA. bool FinishEnroll(const std::string& enroll_response, std::string* server_error); // Creates a |certificate_request| compatible with the Google Attestation CA // for the given |key|, according to the given |profile|, |username| and // |origin|. bool CreateCertificateRequest(const std::string& username, const CertifiedKey& key, CertificateProfile profile, const std::string& origin, std::string* certificate_request, std::string* message_id); // Finishes a certificate request by decoding the |certificate_response| to // recover the |certificate_chain| and storing it in association with the // |key| identified by |username| and |key_label|. Returns true on success. On // failure, returns false and sets |server_error| to the error string from the // CA. bool FinishCertificateRequest(const std::string& certificate_response, const std::string& username, const std::string& key_label, const std::string& message_id, CertifiedKey* key, std::string* certificate_chain, std::string* server_error); // Sends a |request_type| |request| to the Google Attestation CA and waits for // the |reply|. Returns true on success. bool SendACARequestAndBlock(ACARequestType request_type, const std::string& request, std::string* reply); // Creates, certifies, and saves a new |key| for |username| with the given // |key_label|, |key_type|, and |key_usage|. Returns true on success. bool CreateKey(const std::string& username, const std::string& key_label, KeyType key_type, KeyUsage key_usage, CertifiedKey* key); // Finds the |key| associated with |username| and |key_label|. Returns false // if such a key does not exist. bool FindKeyByLabel(const std::string& username, const std::string& key_label, CertifiedKey* key); // Saves the |key| associated with |username| and |key_label|. Returns true on // success. bool SaveKey(const std::string& username, const std::string& key_label, const CertifiedKey& key); // Deletes the key associated with |username| and |key_label|. void DeleteKey(const std::string& username, const std::string& key_label); // Adds named device-wide key to the attestation database. bool AddDeviceKey(const std::string& key_label, const CertifiedKey& key); // Removes a device-wide key from the attestation database. void RemoveDeviceKey(const std::string& key_label); // Creates a PEM certificate chain from the credential fields of a |key|. std::string CreatePEMCertificateChain(const CertifiedKey& key); // Creates a certificate in PEM format from a DER encoded X.509 certificate. std::string CreatePEMCertificate(const std::string& certificate); // Chooses a temporal index which will be used by the ACA to create a // certificate. This decision factors in the currently signed-in |user| and // the |origin| of the certificate request. The strategy is to find an index // which has not already been used by another user for the same origin. int ChooseTemporalIndex(const std::string& user, const std::string& origin); // Creates a Google Attestation CA URL for the given |request_type|. std::string GetACAURL(ACARequestType request_type) const; // Creates a X.509/DER SubjectPublicKeyInfo for the given |key_type| and // |public_key|. On success returns true and provides |public_key_info|. bool GetSubjectPublicKeyInfo(KeyType key_type, const std::string& public_key, std::string* public_key_info) const; base::WeakPtr<AttestationService> GetWeakPtr(); const std::string attestation_ca_origin_; // Other than initialization and destruction, these are used only by the // worker thread. CryptoUtility* crypto_utility_{nullptr}; Database* database_{nullptr}; std::shared_ptr<brillo::http::Transport> http_transport_; KeyStore* key_store_{nullptr}; TpmUtility* tpm_utility_{nullptr}; // Default implementations for the above interfaces. These will be setup // during Initialize() if the corresponding interface has not been set with a // mutator. std::unique_ptr<CryptoUtilityImpl> default_crypto_utility_; std::unique_ptr<DatabaseImpl> default_database_; std::unique_ptr<Pkcs11KeyStore> default_key_store_; std::unique_ptr<chaps::TokenManagerClient> pkcs11_token_manager_; std::unique_ptr<TpmUtilityV1> default_tpm_utility_; // All work is done in the background. This serves to serialize requests and // allow synchronous implementation of complex methods. This is intentionally // declared after the thread-owned members. std::unique_ptr<base::Thread> worker_thread_; // Declared last so any weak pointers are destroyed first. base::WeakPtrFactory<AttestationService> weak_factory_; DISALLOW_COPY_AND_ASSIGN(AttestationService); }; } // namespace attestation #endif // ATTESTATION_SERVER_ATTESTATION_SERVICE_H_