| // Copyright (c) 2012 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 <base/file_path.h> |
| #include <base/synchronization/lock.h> |
| #include <base/threading/platform_thread.h> |
| #include <chromeos/secure_blob.h> |
| #include <openssl/evp.h> |
| |
| #include "attestation.pb.h" |
| |
| namespace cryptohome { |
| |
| class Platform; |
| class Tpm; |
| |
| // 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. |
| class Attestation : public base::PlatformThread::Delegate { |
| public: |
| Attestation(Tpm* tpm, Platform* platform); |
| virtual ~Attestation(); |
| |
| // Must be called before any other method. |
| virtual void Initialize(); |
| |
| // Returns true if the attestation enrollment blobs already exist. |
| virtual bool IsPreparedForEnrollment(); |
| |
| // Returns true if an AIK certificate exists. |
| virtual bool IsEnrolled(); |
| |
| // 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() { |
| base::PlatformThread::Create(0, this, &thread_); |
| } |
| |
| // Verifies all attestation data as an attestation server would. Returns true |
| // if all data is valid. |
| virtual bool Verify(); |
| |
| // Verifies the EK certificate. |
| virtual bool VerifyEK(); |
| |
| // 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_request - The request to be sent to the Privacy CA. |
| // |
| // Returns true on success. |
| virtual bool CreateEnrollRequest(chromeos::SecureBlob* pca_request); |
| |
| // Finishes the enrollment process. On success, IsEnrolled() will return true. |
| // 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_response - The Privacy CA's response to an enrollment request as |
| // returned by CreateEnrollRequest(). |
| // |
| // Returns true on success. |
| virtual bool Enroll(const chromeos::SecureBlob& pca_response); |
| |
| // Creates an attestation certificate request to be sent to the Privacy CA. |
| // The reuest 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 ceritified key. The certificate request process can be finished by |
| // calling FinishCertRequest() with the response from the Privacy CA. This |
| // method can only succeed if IsEnrolled() returns true. |
| // |
| // Parameters |
| // is_cert_for_owner - Whether the certificate is intended for the device |
| // owner. If this is true, the PCA may put more |
| // information into the certificate. |
| // pca_request - The request to be sent to the Privacy CA. |
| // |
| // Returns true on success. |
| virtual bool CreateCertRequest(bool is_cert_for_owner, |
| chromeos::SecureBlob* pca_request); |
| |
| // Finishes the certificate request process. On success, the attestation |
| // certificate generated by the Privacy CA is provided. The response from the |
| // Privacy CA is a serialized AttestationCertificateResponse protobuf. This |
| // final step verifies the PCA operation succeeded and extracts the |
| // certificate for the certified key. |
| // |
| // Parameters |
| // pca_response - The Privacy CA's response to a certificate request as |
| // returned by CreateCertRequest(). |
| // attestation_cert - The certificate generated by the PCA. |
| virtual bool FinishCertRequest(const chromeos::SecureBlob& pca_response, |
| chromeos::SecureBlob* attestation_cert); |
| |
| // Sets an alternative attestation database location. Useful in testing. |
| virtual void set_database_path(const char* path) { |
| database_path_ = FilePath(path); |
| } |
| |
| // PlatformThread::Delegate interface. |
| virtual void ThreadMain() { PrepareForEnrollment(); } |
| |
| private: |
| enum FirmwareType { |
| kUnknown, |
| kVerified, |
| kDeveloper |
| }; |
| static const size_t kQuoteExternalDataSize; |
| static const size_t kCipherKeySize; |
| static const size_t kCipherBlockSize; |
| static const size_t kNonceSize; |
| static const size_t kDigestSize; |
| static const char* kDefaultDatabasePath; |
| static const char* kDefaultPCAPublicKey; |
| static const struct CertificateAuthority { |
| const char* issuer; |
| const char* modulus; // In hex format. |
| } kKnownEndorsementCA[]; |
| static const struct PCRValue { |
| bool developer_mode_enabled; |
| bool recovery_mode_enabled; |
| FirmwareType firmware_type; |
| } kKnownPCRValues[]; |
| |
| Tpm* tpm_; |
| Platform* platform_; |
| base::Lock database_pb_lock_; |
| chromeos::SecureBlob database_key_; |
| FilePath database_path_; |
| AttestationDatabase database_pb_; |
| base::PlatformThreadHandle thread_; |
| |
| // Moves data from a std::string container to a SecureBlob container. |
| chromeos::SecureBlob ConvertStringToBlob(const std::string& s); |
| |
| // Moves data from a chromeos::Blob container to a std::string container. |
| std::string ConvertBlobToString(const chromeos::Blob& blob); |
| |
| // Concatenates two SecureBlobs. |
| chromeos::SecureBlob SecureCat(const chromeos::SecureBlob& blob1, |
| const chromeos::SecureBlob& blob2); |
| |
| // Serializes and encrypts an attestation database. |
| bool EncryptDatabase(const AttestationDatabase& db, |
| EncryptedData* encrypted_db); |
| |
| // Decrypts and parses an attestation database. |
| bool DecryptDatabase(const EncryptedData& encrypted_db, |
| AttestationDatabase* db); |
| |
| // Computes an encrypted database HMAC. |
| std::string ComputeHMAC(const EncryptedData& encrypted_data, |
| const chromeos::SecureBlob& hmac_key); |
| |
| // Writes an encrypted database to a persistent storage location. |
| bool StoreDatabase(const EncryptedData& encrypted_db); |
| |
| // Reads a database from a persistent storage location. |
| bool LoadDatabase(EncryptedData* encrypted_db); |
| |
| // Persists any changes made to database_pb_. |
| bool PersistDatabaseChanges(); |
| |
| // Ensures permissions of the database file are correct. |
| void CheckDatabasePermissions(); |
| |
| // Verifies an endorsement credential against known Chrome OS issuers. |
| bool VerifyEndorsementCredential(const chromeos::SecureBlob& credential, |
| const chromeos::SecureBlob& public_key); |
| |
| // Verifies identity key binding data. |
| bool VerifyIdentityBinding(const IdentityBinding& binding); |
| |
| // Verifies a quote of PCR0. |
| bool VerifyQuote(const chromeos::SecureBlob& aik_public_key, |
| const Quote& quote); |
| |
| // Verifies a certified key. |
| bool VerifyCertifiedKey(const chromeos::SecureBlob& aik_public_key, |
| const chromeos::SecureBlob& certified_public_key, |
| const chromeos::SecureBlob& certified_key_info, |
| const chromeos::SecureBlob& proof); |
| |
| // Creates a public key based on a known credential issuer. |
| EVP_PKEY* GetAuthorityPublicKey(const char* issuer_name); |
| |
| // Verifies an RSA-PKCS1-SHA1 digital signature. |
| bool VerifySignature(const chromeos::SecureBlob& public_key, |
| const chromeos::SecureBlob& signed_data, |
| const chromeos::SecureBlob& signature); |
| |
| // Clears the memory of the database protobuf. |
| void ClearDatabase(); |
| |
| // Clears the memory of a std::string. |
| void ClearString(std::string* s); |
| |
| // Performs AIK activation with a fake credential. |
| bool VerifyActivateIdentity(const chromeos::SecureBlob& delegate_blob, |
| const chromeos::SecureBlob& delegate_secret, |
| const chromeos::SecureBlob& identity_key_blob, |
| const chromeos::SecureBlob& identity_public_key, |
| const chromeos::SecureBlob& ek_public_key); |
| |
| // Encrypts the endorsement credential with the Privacy CA public key. |
| bool EncryptEndorsementCredential(const chromeos::SecureBlob& credential, |
| EncryptedData* encrypted_credential); |
| |
| DISALLOW_COPY_AND_ASSIGN(Attestation); |
| }; |
| |
| } // namespace cryptohome |
| |
| #endif // CRYPTOHOME__ATTESTATION_H_ |