// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine Master // License Agreement. // // Reference implementation of OEMCrypto APIs // #ifndef REF_OEMCRYPTO_ENGINE_REF_H_ #define REF_OEMCRYPTO_ENGINE_REF_H_ #include #include #include #include #include #include #include #include "OEMCryptoCENC.h" #include "file_store.h" #include "oemcrypto_auth_ref.h" #include "oemcrypto_key_ref.h" #include "oemcrypto_rsa_key_shared.h" #include "oemcrypto_session.h" #include "oemcrypto_types.h" #include "oemcrypto_usage_table_ref.h" namespace wvoec_ref { typedef std::map ActiveSessions; static const std::string kStoredUsageTimeFileName = "StoredUsageTime.dat"; typedef struct { // The max time recorded int64_t previous_time; // If the wall time is rollbacked to before the previous_time, this member // is updated to reflect the offset. int64_t rollback_offset; // Pad the struct so that TimeInfo is a multiple of 16. uint8_t padding[16 - (2 * sizeof(time_t)) % 16]; } TimeInfo; // Session types are higher (32 - kSessionIdTypeShift) bits in SessionId. typedef enum SessionType { kSessionTypeOEMCrypto = 0, kSessionTypeEntitledKey = 1, } SessionType; class CryptoEngine { public: static const uint32_t kApiVersion = 16; static const uint32_t kMinorApiVersion = 3; static const int64_t kTimeInfoUpdateWindowInSeconds = 300; // This is like a factory method, except we choose which version to use at // compile time. It is defined in several source files. The build system // should choose which one to use by only linking in the correct one. // NOTE: The caller must instantiate a FileSystem object - ownership // will be transferred to the new CryptoEngine object. static CryptoEngine* MakeCryptoEngine( std::unique_ptr&& file_system); virtual ~CryptoEngine(); virtual bool Initialize(); bool ValidRootOfTrust() const { return root_of_trust_.IsValid(); } OEMCryptoResult InstallKeybox(const uint8_t* keybox, size_t keybox_length) { return root_of_trust_.InstallKeybox(keybox, keybox_length); } OEMCryptoResult InstallTestKeybox(const uint8_t* keybox_data, size_t keybox_length) { return root_of_trust_.InstallTestKeybox(keybox_data, keybox_length); } OEMCryptoResult LoadTestRsaKey() { return root_of_trust_.LoadTestRsaKey(); } OEMCryptoResult IsKeyboxValid() const { return root_of_trust_.IsKeyboxValid(); } std::vector DeviceRootKey() const { return root_of_trust_.DeviceKey(); } OEMCryptoResult GetDeviceRootId(uint8_t* device_id, size_t* device_id_length) const { return root_of_trust_.GetDeviceId(device_id, device_id_length); } std::vector DeviceRootId() const { return root_of_trust_.DeviceId(); } OEMCryptoResult GetRootKeyData(uint8_t* key_data, size_t* key_data_length) const { return root_of_trust_.GetKeyData(key_data, key_data_length); } virtual void Terminate(); virtual SessionId OpenSession(); virtual bool DestroySession(SessionId sid); SessionContext* FindSession(SessionId sid); size_t GetNumberOfOpenSessions() { return sessions_.size(); } size_t GetMaxNumberOfSessions() { // An arbitrary limit for ref implementation. static const size_t kMaxSupportedOEMCryptoSessions = 64; return kMaxSupportedOEMCryptoSessions; } // The OEMCrypto system time. Prevents time rollback. int64_t SystemTime(); // Verify that this nonce does not collide with another nonce in any session. virtual bool NonceCollision(uint32_t nonce); // Returns the HDCP version currently in use. virtual OEMCrypto_HDCP_Capability config_current_hdcp_capability(); // Returns the max HDCP version supported. virtual OEMCrypto_HDCP_Capability config_maximum_hdcp_capability(); // Return true if there might be analog video output enabled. virtual bool analog_display_active() { return !config_local_display_only(); } // Return true if there is an analog display, and CGMS A is turned on. virtual bool cgms_a_active() { return false; } // Return the analog output flags. virtual uint32_t analog_output_flags() { return config_local_display_only() ? OEMCrypto_No_Analog_Output : OEMCrypto_Supports_Analog_Output; } UsageTable& usage_table() { return *(usage_table_.get()); } wvcdm::FileSystem* file_system() { return file_system_.get(); } // If config_local_display_only() returns true, we pretend we are using a // built-in display, instead of HDMI or WiFi output. virtual bool config_local_display_only() { return false; } // A closed platform is permitted to use clear buffers. virtual bool config_closed_platform() { return false; } // Returns true if the client supports persistent storage of // offline usage table information. virtual bool config_supports_usage_table() { return true; } virtual OEMCrypto_ProvisioningMethod config_provisioning_method() { return OEMCrypto_Keybox; } virtual OEMCryptoResult get_oem_certificate(uint8_t* public_cert, size_t* public_cert_length) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } virtual OEMCryptoResult load_oem_private_key(SessionContext* session) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } // Used for OEMCrypto_IsAntiRollbackHwPresent. virtual bool config_is_anti_rollback_hw_present() { return false; } // Returns "L3" for a software only library. L1 is for hardware protected // data paths. virtual const char* config_security_level() { return "L3"; } // This should start at 0, and be incremented only when a security patch has // been applied to the device that fixes a security bug. virtual uint8_t config_security_patch_level() { return 0; } // If 0 no restriction, otherwise it's the max subsample size for // DecryptCENC. This is not the same as the max sample or buffer size. virtual size_t max_subsample_size() { return 4 * 1024 * 1024; } // 4 MiB // If 0 no restriction, otherwise it's the max sample size for DecryptCENC. // This is the same as the max input and output buffer size for DecryptCENC // and CopyBuffer. It is not the same as the max subsample size. virtual size_t max_sample_size() { return 16 * 1024 * 1024; } // 16 MiB virtual bool srm_update_supported() { return false; } virtual OEMCryptoResult current_srm_version(uint16_t* version) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } virtual OEMCryptoResult load_srm(const uint8_t* buffer, size_t buffer_length) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } virtual OEMCryptoResult remove_srm() { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } virtual bool srm_forbidden_device_attached() { return false; } // Rate limit for nonce generation. Default to 200 nonce/second. virtual int nonce_flood_count() { return 200; } // Limit for size of usage table. If this is zero, then the // size is unlimited -- or limited only by memory size. virtual size_t max_usage_table_size() { return 0; } virtual uint32_t resource_rating() { return 1; } // Set destination pointer based on the output destination description. OEMCryptoResult SetDestination( const OEMCrypto_DestBufferDesc& out_description, size_t data_length, uint8_t subsample_flags); // The current destination. uint8_t* destination() { return destination_; } // Subclasses can adjust the destination -- for use in testing. virtual void adjust_destination( const OEMCrypto_DestBufferDesc& out_description, size_t data_length, uint8_t subsample_flags) {} // Push destination buffer to output -- used by subclasses for testing. virtual OEMCryptoResult PushDestination( const OEMCrypto_DestBufferDesc& out_description, uint8_t subsample_flags) { return OEMCrypto_SUCCESS; } // Get the session type bits from |sid|. static uint32_t SessionTypeBits(SessionId sid); protected: // System clock, measuring time in seconds, including anti-rollback offset. int64_t MonotonicTime(); bool LoadOfflineTimeInfo(const std::string& file_path); bool SaveOfflineTimeInfo(const std::string& file_path); std::string GetUsageTimeFileFullPath() const; explicit CryptoEngine(std::unique_ptr&& file_system); virtual SessionContext* MakeSession(SessionId sid); virtual UsageTable* MakeUsageTable(); uint8_t* destination_; ActiveSessions sessions_; AuthenticationRoot root_of_trust_; std::mutex session_table_lock_; std::unique_ptr file_system_; std::unique_ptr usage_table_; TimeInfo offline_time_info_; CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine); }; } // namespace wvoec_ref #endif // REF_OEMCRYPTO_ENGINE_REF_H_