| // Copyright 2018 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CRYPTOHOME_ATTESTATION_H_ |
| #define CRYPTOHOME_ATTESTATION_H_ |
| |
| #include <stdint.h> |
| #include <sys/types.h> |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| |
| #include <base/files/file_path.h> |
| #include <base/scoped_observer.h> |
| #include <base/synchronization/lock.h> |
| #include <base/threading/platform_thread.h> |
| #include <brillo/http/http_transport.h> |
| #include <brillo/secure_blob.h> |
| #include <crypto/scoped_openssl_types.h> |
| #include <dbus/bus.h> |
| #include <google/protobuf/map.h> |
| #include <openssl/evp.h> |
| |
| #include "cryptohome/crypto.h" |
| #include "cryptohome/install_attributes.h" |
| |
| #include "attestation.pb.h" // NOLINT(build/include) |
| |
| namespace cryptohome { |
| |
| class KeyStore; |
| class Pkcs11KeyStore; |
| class Platform; |
| class Tpm; |
| class TpmInit; |
| |
| // Generic result codes for Attestation methods. |
| enum class AttestationResult { |
| kSuccess, |
| kFailure, |
| kInvalidPcr0Value, |
| }; |
| |
| // This class performs tasks which enable attestation enrollment. These tasks |
| // include creating an AIK and recording all information about the AIK and EK |
| // that an attestation server will need to issue credentials for this system. |
| // If a platform does not have a TPM, this class does nothing. This class is |
| // thread-safe. |
| class Attestation : public base::PlatformThread::Delegate, |
| public InstallAttributes::Observer { |
| public: |
| using BooleanMap = google::protobuf::Map<int, bool>; |
| using IdentityCertificateMap = google::protobuf:: |
| Map<int, cryptohome::AttestationDatabase_IdentityCertificate>; |
| |
| static constexpr int kFirstIdentity = 0; |
| |
| enum PCAType { |
| kDefaultPCA, // The Google-operated Privacy CA. |
| kTestPCA, // The test version of the Google-operated Privacy CA. |
| kMaxPCAType |
| }; |
| |
| enum PCARequestType { |
| kEnroll, // Enrolls a device, certifying an identity key. |
| kGetCertificate, // Issues a certificate for a TPM-backed key. |
| }; |
| |
| enum VAType { |
| kDefaultVA, // Verified Access servers. |
| kTestVA, // Test version of the Verified Access servers. |
| kMaxVAType |
| }; |
| |
| Attestation(); |
| virtual ~Attestation(); |
| |
| // Must be called before any other method. If |retain_endorsement_data| is set |
| // then this instance will not perform any finalization of endorsement data. |
| // That is, it will continue to be available in an unencrypted state. |
| // The caller retains ownership of all pointers. If |abe_data| is not an |
| // empty blob, its contents will be used to enable attestation-based |
| // enterprise enrollment. |
| virtual void Initialize(Tpm* tpm, |
| TpmInit* tpm_init, |
| Platform* platform, |
| Crypto* crypto, |
| InstallAttributes* install_attributes, |
| const brillo::SecureBlob& abe_data, |
| bool retain_endorsement_data); |
| |
| // Returns true if the attestation enrollment blobs already exist. |
| virtual bool IsPreparedForEnrollment(); |
| |
| // Returns true if the attestation enrollment blobs already exist for |
| // a given PCA. |
| virtual bool IsPreparedForEnrollmentWith(PCAType pca_type); |
| |
| // Returns true if an AIK certificate exist for one of the Privacy CAs. |
| virtual bool IsEnrolled(); |
| |
| // Returns true if an AIK certificate exist for |pca_type|. |
| virtual bool IsEnrolledWith(PCAType pca_type); |
| |
| // Returns an iterator pointing to the identity certificate for the given |
| // |identity| and given Privacy CA. |
| virtual IdentityCertificateMap::iterator FindIdentityCertificate( |
| int identity, PCAType pca_type); |
| |
| // Returns whether there is an identity certificate for the given |identity| |
| // and given Privacy CA. |
| virtual bool HasIdentityCertificate(int identity, PCAType pca_type); |
| |
| // Returns the count of identities in the attestation database. |
| virtual int GetIdentitiesCount() const; |
| // Returns the identity features of |identity|. |
| virtual int GetIdentityFeatures(int identity) const; |
| |
| // Returns a copy of the identity certificate map. |
| virtual IdentityCertificateMap GetIdentityCertificateMap() const; |
| |
| // Creates attestation enrollment blobs if they do not already exist. This |
| // includes extracting the EK information from the TPM and generating an AIK |
| // to be used later during enrollment. |
| virtual void PrepareForEnrollment(); |
| |
| // Like PrepareForEnrollment(), but asynchronous. |
| virtual void PrepareForEnrollmentAsync(); |
| |
| // Verifies all attestation data as an attestation server would. Returns true |
| // if all data is valid. If |is_cros_core| is true, checks that the EK is |
| // endorsed for that configuration. |
| virtual bool Verify(bool is_cros_core); |
| |
| // Verifies the EK certificate. If |is_cros_core| is true, checks that the EK |
| // is endorsed for that configuration. |
| virtual bool VerifyEK(bool is_cros_core); |
| |
| // Retrieves the EID for the device. The EID is computed and cached as |
| // needed. |
| // Returns false if a transient error prevents the obtention of the EID, |
| // and true if the EID is successfully obtained or definitely cannot be |
| // obtained. |
| virtual bool GetEnterpriseEnrollmentId( |
| brillo::SecureBlob* enterprise_enrollment_id); |
| |
| // Computes the enrollment id and populates the result in |
| // |enterprise_enrollment_id|. If |abe_data_| or endorsement public key is |
| // empty, the |enterprise_enrollment_id| is cleared. |
| // Returns false if a transient error prevents the computation of the EID, |
| // and true if the EID is successfully computed or definitely cannot be |
| // computed. |
| virtual bool ComputeEnterpriseEnrollmentId( |
| brillo::SecureBlob* enterprise_enrollment_id); |
| |
| // Creates an enrollment request to be sent to the Privacy CA. This request |
| // is a serialized AttestationEnrollmentRequest protobuf. Attestation |
| // enrollment is a process by which the Privacy CA verifies the EK certificate |
| // of a device and issues a certificate for an AIK. The enrollment process can |
| // be finished by calling Enroll() with the response from the Privacy CA. This |
| // method can only succeed if IsPreparedForEnrollment() returns true. |
| // |
| // Parameters |
| // pca_type - Specifies to which Privacy CA the request will be sent. |
| // pca_request - The request to be sent to the Privacy CA. |
| // |
| // Returns true on success. |
| virtual bool CreateEnrollRequest(PCAType pca_type, |
| brillo::SecureBlob* pca_request); |
| |
| // Finishes the enrollment process. On success, IsEnrolled() will return true |
| // and GetIdentityCertificate(kFirstIdentity, |pca_type|) will return a |
| // non null value. |
| // |
| // The response from the Privacy CA is a serialized |
| // AttestationEnrollmentResponse protobuf. This method recovers the AIK |
| // certificate by calling TPM_ActivateIdentity and stores this certificate to |
| // be used later during a certificate request. |
| // |
| // Parameters |
| // pca_type - Specifies which Privacy CA created the response. |
| // pca_response - The Privacy CA's response to an enrollment request as |
| // returned by CreateEnrollRequest(). |
| // |
| // Returns true on success. |
| virtual bool Enroll(PCAType pca_type, |
| const brillo::SecureBlob& pca_response); |
| |
| // Performs the complete enrollment process if necessary. On success, |
| // IsEnrolled() will return true and GetIdentityCertificate(kFirstIdentity, |
| // |pca_type|) will return a non null value. |
| // |
| // Parameters |
| // pca_type - Specifies which Privacy CA created the response. |
| // forced - Ignores the current enrollment status and always starts over the |
| // enrollment process. |
| // |
| // Returns true on success. |
| virtual bool EnrollEx(PCAType pca_type, bool forced); |
| |
| // Creates an attestation certificate request to be sent to the Privacy CA. |
| // The request is a serialized AttestationCertificateRequest protobuf. The |
| // certificate request process generates and certifies a key in the TPM and |
| // sends the AIK certificate along with information about the certified key to |
| // the Privacy CA. The PCA verifies the information and issues a certificate |
| // for the certified key. The certificate request process can be finished by |
| // calling FinishCertRequest() with the response from the Privacy CA. This |
| // method can succeed iff GetIdentityCertificate(kFirstIdentity, |pca_type|) |
| // returns a non-null value. |
| // |
| // Parameters |
| // pca_type - Specifies to which Privacy CA the request will be sent. |
| // profile - Specifies the type of certificate to be requested. |
| // username - The user requesting the certificate. |
| // origin - Some certificate requests require information about the origin |
| // of the request. If no origin is needed, this can be empty. |
| // pca_request - The request to be sent to the Privacy CA. |
| // |
| // Returns true on success. |
| virtual bool CreateCertRequest(PCAType pca_type, |
| CertificateProfile profile, |
| const std::string& username, |
| const std::string& origin, |
| brillo::SecureBlob* pca_request); |
| |
| // Finishes the certificate request process. The |pca_response| from the |
| // Privacy CA is a serialized AttestationCertificateResponse protobuf. This |
| // final step verifies that the Privacy CA operation succeeded and extracts |
| // the certificate for the certified key. The certificate is stored with the |
| // key in association with the |key_name|. If the key is a user-specific key |
| // it is stored in association with the currently signed-in user. |
| // |
| // Parameters |
| // pca_response - The Privacy CA's response to a certificate request as |
| // returned by CreateCertRequest(). |
| // is_user_specific - Whether the key is associated with the current user. |
| // username - The canonical username of the active user profile. Ignored if |
| // |is_user_specific| is false. |
| // key_name - A name for the key. If a key already exists with this name it |
| // will be destroyed and replaced with this one. This name may |
| // subsequently be used to query the certificate for the key |
| // using GetCertificateChain. |
| // certificate_chain - The PCA issued certificate chain in PEM format. By |
| // convention the certified key certificate is listed |
| // first followed by intermediate CA certificate(s). |
| // The PCA root certificate is not included. |
| virtual bool FinishCertRequest(const brillo::SecureBlob& pca_response, |
| bool is_user_specific, |
| const std::string& username, |
| const std::string& key_name, |
| brillo::SecureBlob* certificate_chain); |
| |
| // Creates an attestation certificate request and sends it to the Privacy CA. |
| // Then, finishes the certificate request process by checking the sanity of |
| // the response and persisting the result certificate in the key store or |
| // attestation database. If |forced| is set to |false| and the certificate |
| // with |key_name| already exists, just returns the found certificate. The |
| // certification doesn't trigger enrollment process unless |
| // |shall_trigger_enrollment| is set to |true|. |
| // |
| // Parameters |
| // profile - Specifies the type of certificate to be requested. |
| // username - The user requesting the certificate. |
| // origin - Some certificate requests require information about the origin |
| // pca_type - Specifies to which Privacy CA the request will be sent. |
| // of the request. If no origin is needed, this can be empty. |
| // key_name - A name for the key. |
| // forced - If set to |true|, regardless of existence of certificate, always |
| // goes through the certification process. |
| // shall_trigger_enrollment - If set to |true|, the certification triggers |
| // the enrollment process first, if not enrolled |
| // yet. |
| // certificate_chain - The PCA issued certificate chain in PEM format. By |
| // convention the certified key certificate is listed |
| // first followed by intermediate CA certificate(s). |
| // The PCA root certificate is not included. |
| virtual bool GetCertificate(CertificateProfile profile, |
| const std::string& username, |
| const std::string& origin, |
| PCAType pca_type, |
| const std::string& key_name, |
| bool forced, |
| bool shall_trigger_enrollment, |
| brillo::SecureBlob* certificate_chain); |
| |
| // Gets the PCA issued certificate chain for an existing certified key. |
| // Returns true on success. |
| // |
| // Parameters |
| // |
| // is_user_specific - Whether the key is associated with the current user. |
| // username - The canonical username of the active user profile. Ignored if |
| // |is_user_specific| is false. |
| // key_name - The key name; this is the same name previously passed to |
| // FinishCertRequest. |
| // certificate_chain - The PCA issued certificate chain in the same format |
| // used by FinishCertRequest. |
| virtual bool GetCertificateChain(bool is_user_specific, |
| const std::string& username, |
| const std::string& key_name, |
| brillo::SecureBlob* certificate_chain); |
| |
| // Gets the public key for an existing certified key. Returns true on |
| // success. This method is provided for convenience, the same public key can |
| // also be extracted from the certificate chain. |
| // |
| // Parameters |
| // is_user_specific - Whether the key is associated with the current user. |
| // username - The canonical username of the active user profile. Ignored if |
| // |is_user_specific| is false. |
| // key_name - The key name; this is the same name previously passed to |
| // FinishCertRequest. |
| // public_key - The public key, in DER-encoded X.509 SubjectPublicKeyInfo |
| // format. |
| virtual bool GetPublicKey(bool is_user_specific, |
| const std::string& username, |
| const std::string& key_name, |
| brillo::SecureBlob* public_key); |
| |
| // Returns true iff a given key exists. |
| virtual bool DoesKeyExist(bool is_user_specific, |
| const std::string& username, |
| const std::string& key_name); |
| |
| // Signs a challenge for an enterprise device / user. This challenge is |
| // typically generated by and the response verified by DMServer. Returns true |
| // on success. |
| // |
| // This method uses the production Verified Access servers. |
| // |
| // Parameters |
| // |
| // is_user_specific - Whether the key is associated with the current user. |
| // username - The canonical username of the active user profile. Ignored if |
| // |is_user_specific| is false. |
| // key_name - The key name; this is the same name previously passed to |
| // FinishCertRequest. |
| // domain - A domain value to be included in the challenge response. The |
| // value is opaque to this class. |
| // device_id - A device identifier to be included in the challenge response. |
| // This value is opaque to this class. |
| // include_signed_public_key - Whether the challenge response should include |
| // a SignedPublicKeyAndChallenge. |
| // challenge - The challenge to be signed. |
| // response - On success is populated with the challenge response. |
| virtual bool SignEnterpriseChallenge(bool is_user_specific, |
| const std::string& username, |
| const std::string& key_name, |
| const std::string& domain, |
| const brillo::SecureBlob& device_id, |
| bool include_signed_public_key, |
| const brillo::SecureBlob& challenge, |
| brillo::SecureBlob* response); |
| |
| // Signs a challenge for an enterprise device / user. This challenge is |
| // typically generated by and the response verified by DMServer. Returns true |
| // on success. |
| // |
| // Parameters |
| // |
| // va_type - The kind of Verified Access servers to use. |
| // is_user_specific - Whether the key is associated with the current user. |
| // username - The canonical username of the active user profile. Ignored if |
| // |is_user_specific| is false. |
| // key_name - The key name; this is the same name previously passed to |
| // FinishCertRequest. |
| // domain - A domain value to be included in the challenge response. The |
| // value is opaque to this class. |
| // device_id - A device identifier to be included in the challenge response. |
| // This value is opaque to this class. |
| // include_signed_public_key - Whether the challenge response should include |
| // a SignedPublicKeyAndChallenge. |
| // key_name_for_spkac - The name of the key used for |
| // SignedPublicKeyAndChallenge. If empty, the same key |
| // used to sign the challenge response will be used |
| // for SignedPublicKeyAndChallenge. |
| // challenge - The challenge to be signed. |
| // response - On success is populated with the challenge response. |
| virtual bool SignEnterpriseVaChallenge( |
| VAType va_type, |
| bool is_user_specific, |
| const std::string& username, |
| const std::string& key_name, |
| const std::string& domain, |
| const brillo::SecureBlob& device_id, |
| bool include_signed_public_key, |
| const brillo::SecureBlob& challenge, |
| const std::string& key_name_for_spkac, |
| brillo::SecureBlob* response); |
| |
| // Signs a challenge outside of an enterprise context. This challenge is |
| // typically generated by some module running within Chrome. Returns true |
| // on success. |
| // |
| // Parameters |
| // |
| // is_user_specific - Whether the key is associated with the current user. |
| // username - The canonical username of the active user profile. Ignored if |
| // |is_user_specific| is false. |
| // key_name - The key name; this is the same name previously passed to |
| // FinishCertRequest. |
| // challenge - The challenge to be signed. |
| // response - On success is populated with the challenge response. |
| virtual bool SignSimpleChallenge(bool is_user_specific, |
| const std::string& username, |
| const std::string& key_name, |
| const brillo::SecureBlob& challenge, |
| brillo::SecureBlob* response); |
| |
| // Registers a key with the user's PKCS #11 token. On success, the key is |
| // removed from its old location and will no longer be available via this |
| // interface. Returns true on success. |
| // |
| // Parameters |
| // |
| // is_user_specific - Whether the key is associated with the current user. |
| // username - The canonical username of the active user profile. Ignored if |
| // |is_user_specific| is false. |
| // key_name - The key name; this is the same name previously passed to |
| // FinishCertRequest. |
| // include_certificates - Whether to also register the certificate chain |
| // associated with the key. |
| virtual bool RegisterKey(bool is_user_specific, |
| const std::string& username, |
| const std::string& key_name, |
| bool include_certificates); |
| |
| // Gets a payload previously set for a key. If the key exists but no payload |
| // has been set, the payload will be empty. Returns true on success. |
| // |
| // Parameters |
| // |
| // is_user_specific - Whether the key is associated with the current user. |
| // username - The canonical username of the active user profile. Ignored if |
| // |is_user_specific| is false. |
| // key_name - The key name; this is the same name previously passed to |
| // FinishCertRequest. |
| // payload - Receives the payload data. |
| virtual bool GetKeyPayload(bool is_user_specific, |
| const std::string& key_name, |
| const std::string& username, |
| brillo::SecureBlob* payload); |
| |
| // Sets a payload for a key; any previous payload will be overwritten. |
| // Returns true on success. |
| // |
| // Parameters |
| // |
| // is_user_specific - Whether the key is associated with the current user. |
| // username - The canonical username of the active user profile. Ignored if |
| // |is_user_specific| is false. |
| // key_name - The key name; this is the same name previously passed to |
| // FinishCertRequest. |
| // payload - The payload data. |
| virtual bool SetKeyPayload(bool is_user_specific, |
| const std::string& key_name, |
| const std::string& username, |
| const brillo::SecureBlob& payload); |
| |
| // Deletes all keys where the key name has the given |key_prefix|. |
| // Returns true on success. |
| // |
| // Parameters |
| // |
| // is_user_specific - Whether the key is associated with the current user. |
| // username - The current user canonical email address. |
| // key_prefix - The key name prefix. |
| virtual bool DeleteKeysByPrefix(bool is_user_specific, |
| const std::string& username, |
| const std::string& key_prefix); |
| |
| // Deletes a key either from the device or user key store. |
| // Returns false if the key exists but could not be deleted. |
| // Return true if the key did not exist or if it has been deleted. |
| // |
| // Parameters |
| // |
| // is_user_specific - Whether the key is associated with the current user. |
| // username - The current user canonical email address. |
| // key_name - The exact key name of the key to delete. |
| virtual bool DeleteKey(bool is_user_specific, |
| const std::string& username, |
| const std::string& key_name); |
| |
| // Gets the TPM Endorsement Key (EK) certificate and returns it in PEM format |
| // in addition to a hex SHA256 hash of the raw DER encoded certificate. The |
| // result is intended to be human readable and is always valid ASCII. Returns |
| // true on success. This method requires the TPM owner password to be |
| // available. |
| virtual bool GetEKInfo(std::string* ek_info); |
| |
| // Creates a request to be sent to the PCA which will reset the identity for |
| // this device on future AIK enrollments. The |reset_token| is put in the |
| // request protobuf verbatim. On success returns true and copies the |
| // serialized request into |reset_request|. |
| virtual bool GetIdentityResetRequest(const std::string& reset_token, |
| brillo::SecureBlob* reset_request); |
| |
| // Helper method to determine PCR0 status. Returns true iff the current PCR0 |
| // value shows a verified boot measurement. |
| virtual bool IsPCR0VerifiedMode(); |
| |
| // Creates or migrates the default identity and other data. Returns whether |
| // data were migrated or not. |
| virtual bool MigrateAttestationDatabase(); |
| |
| // Ensures all endorsement data which uniquely identifies the device no longer |
| // exists in the attestation database unencrypted. Encrypted endorsement data |
| // cannot be decrypted locally. |
| virtual void FinalizeEndorsementData(); |
| |
| // Provides the owner delegate credentials normally used for AIK activation. |
| // Returns true on success. |
| virtual bool GetDelegateCredentials(brillo::Blob* blob, |
| brillo::Blob* secret, |
| bool* has_reset_lock_permissions); |
| |
| // Provides cached |ek_public_key| and |ek_certificate| if they exist. If only |
| // the public key is found then it will be provided and the certificate will |
| // be empty. Returns false if the public key is not found (i.e. not cached). |
| virtual bool GetCachedEndorsementData(brillo::SecureBlob* ek_public_key, |
| brillo::SecureBlob* ek_certificate); |
| |
| // Caches the endorsement public key if the TPM is not owned. If the TPM is |
| // owned or the public key is already known this will have no effect. |
| virtual void CacheEndorsementData(); |
| |
| // Sends a |request| to a Privacy CA and waits for the |reply|. This is a |
| // blocking call. Returns true on success. |
| virtual bool SendPCARequestAndBlock(PCAType pca_type, |
| PCARequestType request_type, |
| const brillo::SecureBlob& request, |
| brillo::SecureBlob* reply); |
| |
| // Returns a pointer to the enterprise signing key for the |va_type| VA |
| // servers, creating one as needed. |
| virtual RSA* GetEnterpriseSigningKey(VAType va_type); |
| |
| // Returns a pointer to the enterprise encryption key for the |va_type| VA |
| // servers, creating one as needed. |
| virtual RSA* GetEnterpriseEncryptionKey(VAType va_type); |
| |
| // Returns the public key ID for |va_type| VA servers. Note that this |
| // key may have embedded zero characters. |
| virtual std::string GetEnterpriseEncryptionPublicKeyID(VAType type) const; |
| |
| // Sets an alternative attestation database location. Useful in testing. |
| virtual void set_database_path(const char* path) { |
| database_path_ = base::FilePath(path); |
| } |
| |
| // Sets an alternate key store. |
| virtual void set_key_store(KeyStore* key_store) { |
| key_store_ = key_store; |
| } |
| |
| // Sets enterprise keys for testing. The receiver takes ownership of |
| // the keys. |
| virtual void set_enterprise_test_keys(VAType va_type, |
| RSA* signing_key, |
| RSA* encryption_key); |
| |
| virtual void set_http_transport( |
| std::shared_ptr<brillo::http::Transport> transport) { |
| http_transport_ = transport; |
| } |
| |
| // PlatformThread::Delegate interface. |
| virtual void ThreadMain() { PrepareForEnrollment(); } |
| |
| // InstallAttributes::Observer interface. |
| virtual void OnFinalized() { PrepareForEnrollmentAsync(); } |
| |
| // Used by test. |
| void set_default_identity_features_for_test(int default_identity_features); |
| |
| private: |
| typedef std::map<std::string, brillo::SecureBlob> CertRequestMap; |
| enum FirmwareType { |
| kUnknown, |
| kVerified, |
| kDeveloper |
| }; |
| // So we can use std::unique_ptr with openssl types. |
| struct X509Deleter { |
| inline void operator()(void* ptr) const; |
| }; |
| struct NETSCAPE_SPKIDeleter { |
| inline void operator()(void* ptr) const; |
| }; |
| // Just enough CA information to do a basic verification. |
| struct CertificateAuthority { |
| const char* issuer; |
| const char* modulus; // In hex format. |
| }; |
| // A map of enterprise keys by Verified Access server type. |
| using KeysMap = std::map<VAType, crypto::ScopedRSA>; |
| static const size_t kQuoteExternalDataSize; |
| static const size_t kCipherKeySize; |
| static const size_t kNonceSize; |
| static const size_t kDigestSize; |
| static const size_t kChallengeSignatureNonceSize; |
| static const mode_t kDatabasePermissions; |
| static const char kDatabaseOwner[]; |
| static const char kDefaultDatabasePath[]; |
| static const char kDefaultPCAPublicKey[]; |
| static const char kDefaultPCAPublicKeyID[]; |
| static const char kDefaultPCAWebOrigin[]; |
| static const char kTestPCAPublicKey[]; |
| static const char kTestPCAPublicKeyID[]; |
| static const char kTestPCAWebOrigin[]; |
| static const char kDefaultEnterpriseSigningPublicKey[]; |
| static const char kDefaultEnterpriseEncryptionPublicKey[]; |
| static const char kDefaultEnterpriseEncryptionPublicKeyID[]; |
| static const char kTestEnterpriseSigningPublicKey[]; |
| static const char kTestEnterpriseEncryptionPublicKey[]; |
| static const char kTestEnterpriseEncryptionPublicKeyID[]; |
| static const CertificateAuthority kKnownEndorsementCA[]; |
| static const CertificateAuthority kKnownCrosCoreEndorsementCA[]; |
| static const struct PCRValue { |
| bool developer_mode_enabled; |
| bool recovery_mode_enabled; |
| FirmwareType firmware_type; |
| } kKnownPCRValues[]; |
| // ASN.1 DigestInfo header for SHA-256 (see PKCS #1 v2.1 section 9.2). |
| static const unsigned char kSha256DigestInfo[]; |
| static const int kNumTemporalValues; |
| // Install attribute names for alternate PCA attributes. |
| static const char kAlternatePCAKeyAttributeName[]; |
| static const char kAlternatePCAKeyIDAttributeName[]; |
| static const char kAlternatePCAUrlAttributeName[]; |
| // Context name to derive the device stable secret for attestation-based |
| // enterprise enrollment. |
| static const char kAttestationBasedEnterpriseEnrollmentContextName[]; |
| |
| Tpm* tpm_; |
| TpmInit* tpm_init_; |
| Platform* platform_; |
| Crypto* crypto_; |
| brillo::SecureBlob abe_data_; |
| // A lock to protect |database_pb_| because PrepareForEnrollment may happen on |
| // a worker thread. |
| mutable base::Lock lock_; |
| brillo::SecureBlob database_key_; |
| brillo::SecureBlob sealed_database_key_; |
| brillo::SecureBlob enterprise_enrollment_id_; |
| base::FilePath database_path_; |
| AttestationDatabase database_pb_; |
| base::PlatformThreadHandle thread_; |
| CertRequestMap pending_cert_requests_; |
| std::unique_ptr<Pkcs11KeyStore> pkcs11_key_store_; |
| KeyStore* key_store_; |
| KeysMap enterprise_signing_keys_; |
| KeysMap enterprise_encryption_keys_; |
| InstallAttributes* install_attributes_; |
| ScopedObserver<InstallAttributes, InstallAttributes::Observer> |
| install_attributes_observer_; |
| // Don't use directly, use IsTPMReady() instead. |
| bool is_tpm_ready_; |
| bool is_prepare_in_progress_; |
| bool retain_endorsement_data_; |
| // Can be used to override the default transport (e.g. during testing). |
| std::shared_ptr<brillo::http::Transport> http_transport_; |
| // User and group for ownership of the database file. |
| uid_t attestation_user_; |
| gid_t attestation_group_; |
| // Default identity features for newly created identities. |
| int default_identity_features_ = |
| cryptohome::IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID; |
| |
| // Used to retrieve proxy servers from Chrome. |
| scoped_refptr<dbus::Bus> bus_; |
| |
| // Serializes and encrypts an attestation database. |
| AttestationResult EncryptDatabase(const AttestationDatabase& db, |
| std::string* serial_encrypted_db); |
| |
| // Decrypts and parses an attestation database. |
| bool DecryptDatabase(const std::string& serial_encrypted_db, |
| AttestationDatabase* db); |
| |
| // Writes an encrypted database to a persistent storage location. |
| bool StoreDatabase(const std::string& serial_encrypted_db); |
| |
| // Reads a database from a persistent storage location. |
| bool LoadDatabase(std::string* serial_encrypted_db); |
| |
| // Persists any changes made to database_pb_. |
| AttestationResult PersistDatabaseChanges(); |
| |
| // Persists a specific database. Useful for unit tests to set state. |
| AttestationResult PersistDatabase(const AttestationDatabase& db); |
| |
| // Ensures permissions of the database file are correct. |
| void CheckDatabasePermissions(); |
| |
| // Retrieves the EID for the device. The EID is cached as needed. |
| // Returns true on success. |
| Tpm::TpmRetryAction GetEnterpriseEnrollmentIdInternal( |
| brillo::SecureBlob* enterprise_enrollment_id); |
| |
| // Computes the enrollment id and populates the result in |
| // |enterprise_enrollment_id|. If |abe_data_| or endorsement public key is |
| // empty, the |enterprise_enrollment_id| is cleared. |
| Tpm::TpmRetryAction ComputeEnterpriseEnrollmentIdInternal( |
| brillo::SecureBlob* enterprise_enrollment_id); |
| |
| // Creates a new identity. |
| AttestationResult CreateIdentity(const int identity_features, |
| const brillo::SecureBlob& ek_public_key); |
| |
| // Verifies an endorsement credential against known Chrome OS issuers. If |
| // |is_cros_core| is true, checks that the EK is endorsed for that |
| // configuration. |
| bool VerifyEndorsementCredential(const brillo::SecureBlob& credential, |
| const brillo::SecureBlob& public_key, |
| bool is_cros_core); |
| |
| // Verifies identity key binding data. |
| bool VerifyIdentityBinding(const IdentityBinding& binding); |
| |
| // Verifies a quote of PCR0. |
| bool VerifyPCR0Quote(const brillo::SecureBlob& aik_public_key, |
| const Quote& quote); |
| |
| // Verifies a quote of PCR1. |
| bool VerifyPCR1Quote(const brillo::SecureBlob& aik_public_key, |
| const Quote& quote); |
| |
| // Verifies that a quote signature is valid and matches the quoted data. |
| bool VerifyQuoteSignature(const brillo::SecureBlob& aik_public_key, |
| const Quote& quote, |
| uint32_t pcr_index); |
| |
| // Verifies a certified key. |
| bool VerifyCertifiedKey(const brillo::SecureBlob& aik_public_key, |
| const brillo::SecureBlob& certified_public_key, |
| const brillo::SecureBlob& certified_key_info, |
| const brillo::SecureBlob& proof); |
| |
| // Creates a public key based on a known credential issuer. |
| crypto::ScopedEVP_PKEY GetAuthorityPublicKey( |
| const char* issuer_name, |
| bool is_cros_core); |
| |
| // Verifies an RSA-PKCS1-SHA1 digital signature. |
| bool VerifySignature(const brillo::SecureBlob& public_key, |
| const brillo::SecureBlob& signed_data, |
| const brillo::SecureBlob& signature); |
| |
| // Finds the index of the first identity certificate for a PCA. Returns |
| // the number of identity certificates if not found. |
| int GetIndexOfFirstIdentityCertificate(PCAType pca_type); |
| |
| // Copies the deprecated identity-related data into the first identity. |
| // Returns whether data were migrated or not. |
| AttestationResult MigrateIdentityData(); |
| |
| // Clears the memory of the database protobuf. |
| void ClearDatabase(); |
| |
| // Clears the memory of a Quote protobuf. |
| void ClearQuote(Quote* quote); |
| |
| // Clears the memory of all identity-related data. |
| void ClearIdentity(AttestationDatabase::Identity* identity); |
| |
| // Clears the memory of an identity certificate. |
| void ClearIdentityCertificate( |
| AttestationDatabase::IdentityCertificate* identity_certificate); |
| |
| // Clears the memory of a std::string. |
| void ClearString(std::string* s); |
| |
| // Performs AIK activation with a fake credential. |
| bool VerifyActivateIdentity(const brillo::Blob& delegate_blob, |
| const brillo::Blob& delegate_secret, |
| const brillo::SecureBlob& identity_key_blob, |
| const brillo::SecureBlob& identity_public_key, |
| const brillo::SecureBlob& ek_public_key); |
| |
| // Encrypts the endorsement credential with the Privacy CA public key. |
| bool EncryptEndorsementCredential(PCAType pca_type, |
| const brillo::SecureBlob& credential, |
| EncryptedData* encrypted_credential); |
| |
| // Adds named device-wide key to the attestation database. |
| bool AddDeviceKey(const std::string& key_name, const CertifiedKey& key); |
| |
| // Removes a device-wide key from the attestation database. |
| // Returns false if the key exists but could not be deleted. |
| bool RemoveDeviceKey(const std::string& key_name); |
| |
| // Finds a key by name. |
| bool FindKeyByName(bool is_user_specific, |
| const std::string& username, |
| const std::string& key_name, |
| CertifiedKey* key); |
| |
| // Saves a key either in the device or user key store. |
| bool SaveKey(bool is_user_specific, |
| const std::string& username, |
| const std::string& key_name, |
| const CertifiedKey& key); |
| |
| // Assembles a certificate chain in PEM format for a certified key. By |
| // convention, the leaf certificate will be first. |
| bool CreatePEMCertificateChain(const CertifiedKey& key, |
| brillo::SecureBlob* certificate_chain); |
| |
| // Creates a certificate in PEM format from a DER encoded X.509 certificate. |
| std::string CreatePEMCertificate(const std::string& certificate); |
| |
| // Signs data with a certified key using the scheme specified for challenges |
| // and outputs a serialized SignedData protobuf. |
| bool SignChallengeData(const CertifiedKey& key, |
| const brillo::SecureBlob& challenge, |
| brillo::SecureBlob* response); |
| |
| // Validates incoming enterprise challenge data. |
| bool ValidateEnterpriseChallenge(VAType va_type, |
| const SignedData& signed_challenge); |
| |
| // Encrypts a KeyInfo protobuf as required for an enterprise challenge |
| // response. |
| bool EncryptEnterpriseKeyInfo(VAType va_type, const KeyInfo& key_info, |
| EncryptedData* encrypted_data); |
| |
| // Encrypts data into an EncryptedData protobuf, wrapping the encryption key |
| // with |wrapping_key|. |
| bool EncryptData(const brillo::SecureBlob& input, |
| RSA* wrapping_key, |
| const std::string& wrapping_key_id, |
| EncryptedData* output); |
| |
| // Creates an RSA* given a modulus in hex format. The exponent is always set |
| // to 65537. If an error occurs, NULL is returned. |
| crypto::ScopedRSA CreateRSAFromHexModulus(const std::string& hex_modulus); |
| |
| // Creates a SignedPublicKeyAndChallenge with a random challenge. |
| bool CreateSignedPublicKey(const CertifiedKey& key, |
| brillo::SecureBlob* signed_public_key); |
| |
| // Standard AES-256-CBC padded encryption. |
| bool AesEncrypt(const brillo::SecureBlob& plaintext, |
| const brillo::SecureBlob& key, |
| const brillo::SecureBlob& iv, |
| brillo::SecureBlob* ciphertext); |
| |
| // Standard AES-256-CBC padded decryption. |
| bool AesDecrypt(const brillo::SecureBlob& ciphertext, |
| const brillo::SecureBlob& key, |
| const brillo::SecureBlob& iv, |
| brillo::SecureBlob* plaintext); |
| |
| // Encrypts data in a TSS compatible way using AES-256-CBC. |
| // |
| // Parameters |
| // key - The AES key. |
| // input - The data to be encrypted. |
| // output - The encrypted data. |
| bool TssCompatibleEncrypt(const brillo::SecureBlob& key, |
| const brillo::SecureBlob& input, |
| brillo::SecureBlob* output); |
| |
| // Chooses a temporal index which will be used by the PCA 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); |
| |
| // Returns true if the TPM is ready. |
| bool IsTPMReady(); |
| |
| // If PCR1 is clear (i.e. all 0 bytes), extends the PCR with the HWID. This is |
| // a fallback if the device firmware does not already do this. |
| void ExtendPCR1IfClear(); |
| |
| // Quote the given PCR and fill the result in the Quote object |
| AttestationResult CreatePCRQuote(uint32_t pcr_index, |
| const brillo::SecureBlob& identity_key_blob, |
| Quote* output); |
| |
| // Creates a PCA URL for the given |pca_type| and |request_type|. |
| std::string GetPCAURL(PCAType pca_type, PCARequestType request_type) const; |
| |
| // Retrieves the endorsement public key from cache or by asking the TPM if |
| // possible. |
| Tpm::TpmRetryAction GetTpmEndorsementPublicKey( |
| brillo::SecureBlob* ek_public_key); |
| |
| // Computes the enterprise DEN for attestation-based enrollment and |
| // stores it in |enterprise_enrollment_nonce|. |
| void ComputeEnterpriseEnrollmentNonce( |
| brillo::SecureBlob* enterprise_enrollment_nonce); |
| |
| // Sends a |request| to a Privacy CA with |transport| and waits for the |
| // |reply|. This is a blocking call. Returns true on success. Though we |
| // already provide the server URL, it is still specialized for pca request |
| // because of the way it processes the PCA request. |
| bool SendPCARequestWithTransportAndBlock( |
| const std::string& pca_server_url, |
| std::shared_ptr<brillo::http::Transport> transport, |
| const brillo::SecureBlob& request, |
| brillo::SecureBlob* reply); |
| |
| // Sends a |request| to a Privacy CA with proxy servers and waits for the |
| // |reply|. This is a blocking call. Returns true on success. |
| bool SendPCARequestWithProxyAndBlock(PCAType pca_type, |
| PCARequestType request_type, |
| const brillo::SecureBlob& request, |
| brillo::SecureBlob* reply); |
| |
| // Initializes dbus in order to get proxy information from Chrome. |
| bool InitializeDBus(); |
| |
| // Injects a TpmInit object to be used for RemoveTpmOwnerDependency |
| void set_tpm_init(TpmInit* value) { tpm_init_ = value; } |
| |
| friend class AttestationBaseTest; |
| |
| DISALLOW_COPY_AND_ASSIGN(Attestation); |
| }; |
| |
| } // namespace cryptohome |
| |
| #endif // CRYPTOHOME_ATTESTATION_H_ |