Files
android/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h
Alex Dale 23f7cd60a7 Sync Android reference with CDM reference.
The sc-dev branch on Android is out of sync with several important
changes on the CDM master branch.  This changes copies several CLs.

[ Merge of http://go/wvgerrit/104524 ]

OEMCrypto unittest: generic crypto APIs

Add unit tests to verify that generic crypto APIs do not crash for large
input buffer lengths and signature lengths.

[ Merge of http://go/wvgerrit/106583 ]

Fix secure buffer tests in OEMCrypto testbed

The secure buffers were not being used correctly in the testbed, and
were failing OEMCryptoMemoryCopyBufferForHugeBufferLengths.

[ Merge of http://go/wvgerrit/109603 ]

Reject block_offsets of 16 or greater in OEC Ref

This is a potential security hole. We will be enforcing that OEMCrypto
rejects this in an upcoming test, so the Ref must be updated to reject
it.

[ Merge of http://go/wvgerrit/110165 ]

Fix Format String Signedness

See above for full description.

[ Merge of http://go/wvgerrit/111784 ]

Fix heap overflow test in L3 and OEMCrypto ref

Check the length of wrapped_rsa_key_length before casting to
WrappedRSAKey struct.

[ Merge of http://go/wvgerrit/113563 ]

Reword "blacklisted" to "forbidden"

[ Merge of http://go/wvgerrit/113583 ]

Use error code from RAND_bytes

The return code from RAND_bytes was not used correctly.

[ Merge of http://go/wvgerrit/113644 ]

Check for buffer overflow when computing subsample size

The test DecryptCENCForNumBytesClearPlusEncryptedOverflowsSize
cleverly picks num_bytes_clear + num_bytes_encrypted = 1 after integer
overflow. This is in the refernce code, level 3, and odkitee.

[ Merge of http://go/wvgerrit/113683 ]

OEMCrypto reference code: respect analog flags for clear buffers

The reference code should honor the analog_display_active flag for
both clear and secure buffers.

[ Merge of http://go/wvgerrit/114883 ]

Add size check for IV in OEMCrypto APIs

IV is supposed to be 16 bytes but the size is never checked before iv
gets used in LoadProvisioning.

Bug: 145026457
Bug: 147569428
Bug: 159847851
Bug: 162372059
Bug: 169278035
Bug: 169980065
Bug: 173460694
Bug: 173994023
Bug: 174523584
Bug: 175001473
Bug: 175041667
Test: No compiled files changed
Change-Id: If0ccd1cd3a56f72eedd2a6cb202a34bc7b43ca0d
2021-03-08 19:45:05 -08:00

255 lines
8.6 KiB
C++

// 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 <stdint.h>
#include <time.h>
#include <map>
#include <memory>
#include <mutex>
#include <vector>
#include <openssl/rsa.h>
#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<SessionId, SessionContext*> 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<wvcdm::FileSystem>&& file_system);
virtual ~CryptoEngine();
virtual bool Initialize();
bool ValidRootOfTrust() { return root_of_trust_.Validate(); }
bool InstallKeybox(const uint8_t* keybox, size_t keybox_length) {
return root_of_trust_.InstallKeybox(keybox, keybox_length);
}
bool UseTestKeybox(const uint8_t* keybox_data, size_t keybox_length) {
return root_of_trust_.UseTestKeybox(keybox_data, keybox_length);
}
bool LoadTestRsaKey() { return root_of_trust_.LoadTestRsaKey(); }
KeyboxError ValidateKeybox() { return root_of_trust_.ValidateKeybox(); }
const std::vector<uint8_t>& DeviceRootKey() {
return root_of_trust_.DeviceKey();
}
const std::vector<uint8_t>& DeviceRootId() {
return root_of_trust_.DeviceId();
}
size_t DeviceRootTokenLength() { return root_of_trust_.DeviceTokenLength(); }
const uint8_t* DeviceRootToken() { return root_of_trust_.DeviceToken(); }
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<wvcdm::FileSystem>&& 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<wvcdm::FileSystem> file_system_;
std::unique_ptr<UsageTable> usage_table_;
TimeInfo offline_time_info_;
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
};
} // namespace wvoec_ref
#endif // REF_OEMCRYPTO_ENGINE_REF_H_