Source release 18.1.0
This commit is contained in:
@@ -27,8 +27,6 @@
|
||||
#include "oemcrypto_types.h"
|
||||
#include "pst_report.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// GTest requires PrintTo to be in the same namespace as the thing it prints,
|
||||
// which is std::vector in this case.
|
||||
namespace std {
|
||||
@@ -38,13 +36,15 @@ void PrintTo(const vector<uint8_t>& value, ostream* os);
|
||||
} // namespace std
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
using namespace std;
|
||||
|
||||
// OEMCrypto Fuzzing: Set max signture length to 1mb.
|
||||
const size_t MB = 1024 * 1024;
|
||||
|
||||
// Make sure this is larger than kMaxKeysPerSession, in oemcrypto_test.cpp
|
||||
// Make sure this is larger than kMaxKeysPerSession.
|
||||
constexpr size_t kMaxNumKeys = 30;
|
||||
|
||||
namespace {
|
||||
#if defined(TEST_SPEED_MULTIPLIER) // Can slow test time limits when
|
||||
// debugging is slowing everything.
|
||||
constexpr int kSpeedMultiplier = TEST_SPEED_MULTIPLIER;
|
||||
@@ -57,7 +57,6 @@ constexpr uint32_t kDuration = 2 * kSpeedMultiplier;
|
||||
constexpr uint32_t kLongDuration = 5 * kSpeedMultiplier;
|
||||
constexpr int32_t kTimeTolerance = 3 * kSpeedMultiplier;
|
||||
constexpr int64_t kUsageTableTimeTolerance = 10 * kSpeedMultiplier;
|
||||
} // namespace
|
||||
|
||||
// Note: The API does not specify a maximum key id length. We specify a
|
||||
// maximum just for these tests, so that we have a fixed message size.
|
||||
@@ -158,7 +157,7 @@ class RoundTrip {
|
||||
required_request_signature_size_(0),
|
||||
encrypted_response_length_(0),
|
||||
response_signature_length_(0) {}
|
||||
virtual ~RoundTrip() {}
|
||||
virtual ~RoundTrip() = default;
|
||||
|
||||
// Have OEMCrypto sign a request message and then verify the signature and the
|
||||
// core message.
|
||||
@@ -306,7 +305,7 @@ class ProvisioningRoundTrip
|
||||
size_t* wrapped_key_length);
|
||||
// This takes a pointer in the response_data_ and remaps it to the same
|
||||
// pointer within the encrypted message. This is used for backwards
|
||||
// compatibliity testing, so that a v15 oemcrypto will accept range checks.
|
||||
// compatibility testing, so that a v15 oemcrypto will accept range checks.
|
||||
template <typename T>
|
||||
const T* RemapPointer(const T* response_pointer) const;
|
||||
|
||||
@@ -319,18 +318,119 @@ class ProvisioningRoundTrip
|
||||
std::vector<uint8_t> wrapped_rsa_key_;
|
||||
};
|
||||
|
||||
class Provisioning40RoundTrip
|
||||
: public RoundTrip<
|
||||
/* CoreRequest */ oemcrypto_core_message::ODK_Provisioning40Request,
|
||||
OEMCrypto_PrepAndSignProvisioningRequest,
|
||||
/* CoreResponse */ ODK_ParsedProvisioning,
|
||||
/* ResponseData */ Prov40CertMessage> {
|
||||
public:
|
||||
Provisioning40RoundTrip(Session* session)
|
||||
: RoundTrip(session), allowed_schemes_(kSign_RSASSA_PSS) {}
|
||||
void PrepareSession(bool is_oem_key);
|
||||
|
||||
// Not used. Use Load*CertResponse() below to load OEM/DRM response
|
||||
// respectively.
|
||||
void CreateDefaultResponse() override{};
|
||||
void EncryptAndSignResponse() override{};
|
||||
OEMCryptoResult LoadResponse(Session* session) override {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
OEMCryptoResult LoadOEMCertResponse();
|
||||
OEMCryptoResult LoadDRMCertResponse();
|
||||
|
||||
const std::vector<uint8_t>& wrapped_oem_key() { return wrapped_oem_key_; }
|
||||
const std::vector<uint8_t>& oem_public_key() { return oem_public_key_; }
|
||||
OEMCrypto_PrivateKeyType oem_key_type() { return oem_key_type_; }
|
||||
const std::vector<uint8_t>& wrapped_drm_key() { return wrapped_drm_key_; }
|
||||
const std::vector<uint8_t>& drm_public_key() { return drm_public_key_; }
|
||||
OEMCrypto_PrivateKeyType drm_key_type() { return drm_key_type_; }
|
||||
void set_allowed_schemes(uint32_t allowed_schemes) {
|
||||
allowed_schemes_ = allowed_schemes;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool RequestHasNonce() override { return true; }
|
||||
void VerifyRequestSignature(const vector<uint8_t>& data,
|
||||
const vector<uint8_t>& generated_signature,
|
||||
size_t core_message_length) override;
|
||||
// Verify the values of the core response.
|
||||
virtual void FillAndVerifyCoreRequest(
|
||||
const std::string& core_message_string) override;
|
||||
|
||||
uint32_t allowed_schemes_;
|
||||
std::vector<uint8_t> wrapped_oem_key_;
|
||||
std::vector<uint8_t> oem_public_key_;
|
||||
OEMCrypto_PrivateKeyType oem_key_type_;
|
||||
std::vector<uint8_t> wrapped_drm_key_;
|
||||
std::vector<uint8_t> drm_public_key_;
|
||||
OEMCrypto_PrivateKeyType drm_key_type_;
|
||||
};
|
||||
|
||||
class Provisioning40CastRoundTrip
|
||||
: public RoundTrip<
|
||||
/* CoreRequest */ oemcrypto_core_message::ODK_Provisioning40Request,
|
||||
OEMCrypto_PrepAndSignProvisioningRequest,
|
||||
/* CoreResponse */ ODK_ParsedProvisioning,
|
||||
/* ResponseData */ RSAPrivateKeyMessage> {
|
||||
public:
|
||||
Provisioning40CastRoundTrip(Session* session,
|
||||
const std::vector<uint8_t>& encoded_rsa_key)
|
||||
: RoundTrip(session), encryptor_(),
|
||||
encoded_rsa_key_(encoded_rsa_key) {}
|
||||
|
||||
void PrepareSession();
|
||||
void LoadDRMPrivateKey();
|
||||
void CreateDefaultResponse() override;
|
||||
void SignResponse();
|
||||
void EncryptAndSignResponse() override;
|
||||
OEMCryptoResult LoadResponse() override { return LoadResponse(session_); }
|
||||
OEMCryptoResult LoadResponse(Session* session) override;
|
||||
OEMCryptoResult LoadResponseNoRetry(Session* session, size_t* wrapped_key_length) ;
|
||||
|
||||
// Returned
|
||||
const std::vector<uint8_t>& wrapped_drm_key() { return wrapped_drm_key_; }
|
||||
const std::vector<uint8_t>& wrapped_rsa_key() { return wrapped_rsa_key_; }
|
||||
const std::vector<uint8_t>& drm_public_key() { return drm_public_key_; }
|
||||
OEMCrypto_PrivateKeyType drm_key_type() { return drm_key_type_; }
|
||||
void set_allowed_schemes(uint32_t allowed_schemes) {
|
||||
allowed_schemes_ = allowed_schemes;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool RequestHasNonce() override { return true; }
|
||||
void VerifyRequestSignature(const vector<uint8_t>& data,
|
||||
const vector<uint8_t>& generated_signature,
|
||||
size_t core_message_length) override;
|
||||
// Verify the values of the core response.
|
||||
virtual void FillAndVerifyCoreRequest(
|
||||
const std::string& core_message_string) override;
|
||||
|
||||
uint32_t allowed_schemes_;
|
||||
Encryptor encryptor_;
|
||||
std::vector<uint8_t> wrapped_oem_key_;
|
||||
std::vector<uint8_t> oem_public_key_;
|
||||
OEMCrypto_PrivateKeyType oem_key_type_;
|
||||
std::vector<uint8_t> wrapped_drm_key_;
|
||||
std::vector<uint8_t> drm_public_key_;
|
||||
OEMCrypto_PrivateKeyType drm_key_type_;
|
||||
std::vector<uint8_t> encoded_rsa_key_;
|
||||
std::vector<uint8_t> wrapped_rsa_key_;
|
||||
};
|
||||
|
||||
class LicenseRoundTrip
|
||||
: public RoundTrip<
|
||||
/* CoreRequest */ oemcrypto_core_message::ODK_LicenseRequest,
|
||||
OEMCrypto_PrepAndSignLicenseRequest,
|
||||
/* CoreResponse */ ODK_ParsedLicense,
|
||||
/* CoreResponse */ ODK_Packing_ParsedLicense,
|
||||
/* ResponseData */ MessageData> {
|
||||
public:
|
||||
LicenseRoundTrip(Session* session)
|
||||
: RoundTrip(session),
|
||||
control_(wvoec::kControlNonceEnabled),
|
||||
num_keys_(4),
|
||||
pst_(""),
|
||||
pst_(),
|
||||
minimum_srm_version_(0),
|
||||
update_mac_keys_(true),
|
||||
api_version_(kCurrentAPI),
|
||||
@@ -349,7 +449,7 @@ class LicenseRoundTrip
|
||||
void InjectFuzzedResponseData(const uint8_t* data, size_t size);
|
||||
// Used for OEMCrypto Fuzzing: Convert boolean flags in parsed_license to
|
||||
// valid bytes to avoid errors from msan.
|
||||
void ConvertDataToValidBools(ODK_ParsedLicense* t);
|
||||
void ConvertDataToValidBools(ODK_Packing_ParsedLicense* t);
|
||||
// Create a license with four keys. Each key is responsible for one of generic
|
||||
// encrypt (key 0), decrypt (key 1), sign (key 2) and verify (key 3). Each key
|
||||
// is allowed only one type of operation.
|
||||
@@ -444,6 +544,9 @@ class LicenseRoundTrip
|
||||
// CreateDefaultResponse.
|
||||
OEMCrypto_LicenseType license_type_;
|
||||
uint8_t request_hash_[ODK_SHA256_HASH_SIZE];
|
||||
// Used to hold and add/update key information to be transferred into the core
|
||||
// response later on.
|
||||
std::vector<OEMCrypto_KeyObject> key_array_;
|
||||
};
|
||||
|
||||
class RenewalRoundTrip
|
||||
@@ -466,7 +569,7 @@ class RenewalRoundTrip
|
||||
void EncryptAndSignResponse() override;
|
||||
void InjectFuzzedResponseData(OEMCrypto_Renewal_Response_Fuzz& fuzzed_data,
|
||||
const uint8_t* renewal_response,
|
||||
const size_t renewal_response_size);
|
||||
size_t renewal_response_size);
|
||||
OEMCryptoResult LoadResponse() override { return LoadResponse(session_); }
|
||||
OEMCryptoResult LoadResponse(Session* session) override;
|
||||
uint64_t renewal_duration_seconds() const {
|
||||
@@ -571,7 +674,7 @@ class Session {
|
||||
// and also fill out enc_key_, mac_key_server_, and mac_key_client_.
|
||||
void GenerateDerivedKeysFromSessionKey();
|
||||
// Encrypt some data and pass to OEMCrypto_DecryptCENC to verify decryption.
|
||||
void TestDecryptCTR(bool select_key_first = true,
|
||||
void TestDecryptCTR(bool get_fresh_key_handle_first = true,
|
||||
OEMCryptoResult expected_result = OEMCrypto_SUCCESS,
|
||||
size_t key_index = 0);
|
||||
// Encrypt some data and pass to OEMCrypto_DecryptCENC to verify decryption
|
||||
@@ -580,9 +683,9 @@ class Session {
|
||||
OEMCrypto_SESSION session = 0,
|
||||
const uint8_t* content_key_id = nullptr,
|
||||
size_t content_key_id_length = 0);
|
||||
// Verify that an attempt to select an expired key either succeeds, or gives
|
||||
// an actionable error code.
|
||||
void TestSelectExpired(size_t key_index);
|
||||
// Verify that an attempt to get a key handle for an expired key either
|
||||
// succeeds or gives an actionable error code.
|
||||
void TestGetKeyHandleExpired(size_t key_index);
|
||||
// Calls OEMCrypto_GetOEMPublicCertificate and OEMCrypto_LoadOEMPrivateKey and
|
||||
// loads the OEM cert's public rsa key into public_rsa_.
|
||||
void LoadOEMCert(bool verify_cert = false);
|
||||
@@ -593,7 +696,7 @@ class Session {
|
||||
vector<uint8_t>* wrapped_key, bool force);
|
||||
// Loads the default test RSA public key into public_rsa_.
|
||||
void SetTestRsaPublicKey();
|
||||
// Loads the specified DRM public key into the appropriate key.
|
||||
// Loads the specified DRM or OEM public key into the appropriate key.
|
||||
// The provided key is serialized as an ASN.1 DER encoded PrivateKeyInfo.
|
||||
void SetPublicKeyFromPrivateKeyInfo(OEMCrypto_PrivateKeyType key_type,
|
||||
const uint8_t* buffer, size_t length);
|
||||
@@ -604,7 +707,7 @@ class Session {
|
||||
// The provided key is serialized as an ASN.1 DER encoded PrivateKeyInfo.
|
||||
void SetEccPublicKeyFromPrivateKeyInfo(const uint8_t* buffer, size_t length);
|
||||
|
||||
// Loads the specified DRM public key into the appropriate key.
|
||||
// Loads the specified DRM or OEM public key into the appropriate key.
|
||||
// The provided key is serialized as an ASN.1 DER encoded SubjectPublicKey.
|
||||
void SetPublicKeyFromSubjectPublicKey(OEMCrypto_PrivateKeyType key_type,
|
||||
const uint8_t* buffer, size_t length);
|
||||
@@ -721,16 +824,29 @@ class Session {
|
||||
|
||||
void set_license(const MessageData& license) { license_ = license; }
|
||||
|
||||
// Gives access to the last key handle used by the Session. Useful if a test
|
||||
// case uses one of the decrypt test functions above and then wants to perform
|
||||
// further crypto operations using the same key handle. Also useful if a test
|
||||
// case needs to inject a specific erroneous key handle into the decrypt test
|
||||
// functions.
|
||||
vector<uint8_t>& key_handle() { return key_handle_; }
|
||||
|
||||
const KeyDeriver& key_deriver() const { return key_deriver_; }
|
||||
void set_mac_keys(const uint8_t* mac_keys) {
|
||||
key_deriver_.set_mac_keys(mac_keys);
|
||||
}
|
||||
bool IsPublicKeySet() {
|
||||
return public_rsa_ != nullptr || public_ec_ != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
OEMCryptoResult GetKeyHandle(
|
||||
vector<uint8_t>& key_handle, size_t key_index = 0,
|
||||
OEMCryptoCipherMode cipher_mode = OEMCrypto_CipherMode_CENC);
|
||||
// This compares the actual result with the expected result. If OEMCrypto is
|
||||
// an older version, we allow it to report an equivalent error code.
|
||||
void TestDecryptResult(OEMCryptoResult expected_result,
|
||||
OEMCryptoResult actual_select_result,
|
||||
OEMCryptoResult actual_getkeyhandle_result,
|
||||
OEMCryptoResult actual_decryt_result);
|
||||
|
||||
bool open_ = false;
|
||||
@@ -756,6 +872,7 @@ class Session {
|
||||
static std::mutex ephemeral_key_map_lock_;
|
||||
vector<uint8_t> pst_report_buffer_;
|
||||
MessageData license_ = {};
|
||||
vector<uint8_t> key_handle_;
|
||||
|
||||
vector<uint8_t> encrypted_usage_entry_;
|
||||
uint32_t usage_entry_number_ = 0;
|
||||
@@ -773,6 +890,19 @@ template <PrepAndSignRequest_t PrepAndSignRequest>
|
||||
void GetDefaultRequestSignatureAndCoreMessageLengths(
|
||||
uint32_t& session_id, const size_t& small_size,
|
||||
size_t* gen_signature_length, size_t* core_message_length);
|
||||
// Loads the key matching the given |key_id| into the |session| in OEMCrypto for
|
||||
// the given |cipher_mode| and returns a handle to that key. This function
|
||||
// handles negotiating the size of the |key_handle| buffer. For non-bypassing
|
||||
// systems, this is equivalent to the old SelectKey call and will deselect any
|
||||
// previous keys selected in the session. For bypassing systems, multiple key
|
||||
// handles may be valid simultaneously, but this call may invalidate any
|
||||
// previous handles.
|
||||
OEMCryptoResult GetKeyHandleIntoVector(OEMCrypto_SESSION session,
|
||||
const uint8_t* key_id,
|
||||
size_t key_id_length,
|
||||
OEMCryptoCipherMode cipher_mode,
|
||||
vector<uint8_t>& key_handle);
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // CDM_OEC_SESSION_UTIL_H_
|
||||
|
||||
Reference in New Issue
Block a user