Merge OEMCrypto KDF and usage functions
Since KDF functions are only used right before specific functions, this merges them to simplify internal state within OEMCrypto. Fixes: 299527712 Change-Id: I426cfcdc102bd73cf65cd809b213da2474f44b34
This commit is contained in:
committed by
Robert Shih
parent
b04fda2908
commit
488a4647db
@@ -125,6 +125,7 @@ class CertificateProvisioning {
|
|||||||
std::unique_ptr<CryptoSession> crypto_session_;
|
std::unique_ptr<CryptoSession> crypto_session_;
|
||||||
CdmCertificateType cert_type_;
|
CdmCertificateType cert_type_;
|
||||||
std::unique_ptr<ServiceCertificate> service_certificate_;
|
std::unique_ptr<ServiceCertificate> service_certificate_;
|
||||||
|
std::string request_;
|
||||||
// The wrapped private key in provisioning 4 generated by calling
|
// The wrapped private key in provisioning 4 generated by calling
|
||||||
// GenerateCertificateKeyPair. It will be saved to file system if a valid
|
// GenerateCertificateKeyPair. It will be saved to file system if a valid
|
||||||
// response is received.
|
// response is received.
|
||||||
|
|||||||
@@ -24,13 +24,6 @@ class ContentKeySession : public KeySession {
|
|||||||
|
|
||||||
KeySessionType Type() override { return kDefault; }
|
KeySessionType Type() override { return kDefault; }
|
||||||
|
|
||||||
// Generate Derived Keys for ContentKeySession
|
|
||||||
OEMCryptoResult GenerateDerivedKeys(const std::string& message) override;
|
|
||||||
|
|
||||||
// Generate Derived Keys (from session key) for ContentKeySession
|
|
||||||
OEMCryptoResult GenerateDerivedKeys(const std::string& message,
|
|
||||||
const std::string& session_key) override;
|
|
||||||
|
|
||||||
// Load Keys for ContentKeySession
|
// Load Keys for ContentKeySession
|
||||||
OEMCryptoResult LoadKeys(const std::string& message,
|
OEMCryptoResult LoadKeys(const std::string& message,
|
||||||
const std::string& signature,
|
const std::string& signature,
|
||||||
|
|||||||
@@ -159,7 +159,9 @@ class CryptoSession {
|
|||||||
OEMCrypto_SignatureHashAlgorithm& algorithm);
|
OEMCrypto_SignatureHashAlgorithm& algorithm);
|
||||||
virtual CdmResponseType UseSecondaryKey(bool dual_key);
|
virtual CdmResponseType UseSecondaryKey(bool dual_key);
|
||||||
// V16 licenses.
|
// V16 licenses.
|
||||||
virtual CdmResponseType LoadLicense(const std::string& signed_message,
|
virtual CdmResponseType LoadLicense(const std::string& context,
|
||||||
|
const std::string& session_key,
|
||||||
|
const std::string& signed_message,
|
||||||
const std::string& core_message,
|
const std::string& core_message,
|
||||||
const std::string& signature,
|
const std::string& signature,
|
||||||
CdmLicenseKeyType key_type);
|
CdmLicenseKeyType key_type);
|
||||||
@@ -178,17 +180,19 @@ class CryptoSession {
|
|||||||
const std::vector<CryptoKey>& key_array);
|
const std::vector<CryptoKey>& key_array);
|
||||||
|
|
||||||
// Provisioning request/responses
|
// Provisioning request/responses
|
||||||
virtual CdmResponseType GenerateDerivedKeys(const std::string& message);
|
|
||||||
virtual CdmResponseType GenerateDerivedKeys(const std::string& message,
|
|
||||||
const std::string& session_key);
|
|
||||||
virtual CdmResponseType PrepareAndSignProvisioningRequest(
|
virtual CdmResponseType PrepareAndSignProvisioningRequest(
|
||||||
const std::string& message, std::string* core_message,
|
const std::string& message, std::string* core_message,
|
||||||
std::string* signature, bool& should_specify_algorithm,
|
std::string* signature, bool& should_specify_algorithm,
|
||||||
OEMCrypto_SignatureHashAlgorithm& algorithm);
|
OEMCrypto_SignatureHashAlgorithm& algorithm);
|
||||||
virtual CdmResponseType LoadProvisioning(const std::string& signed_message,
|
virtual CdmResponseType LoadProvisioning(const std::string& request,
|
||||||
|
const std::string& signed_message,
|
||||||
const std::string& core_message,
|
const std::string& core_message,
|
||||||
const std::string& signature,
|
const std::string& signature,
|
||||||
std::string* wrapped_private_key);
|
std::string* wrapped_private_key);
|
||||||
|
virtual CdmResponseType LoadProvisioningCast(
|
||||||
|
const std::string& derivation_key, const std::string& request,
|
||||||
|
const std::string& signed_message, const std::string& core_message,
|
||||||
|
const std::string& signature, std::string* wrapped_private_key);
|
||||||
virtual CdmResponseType LoadCertificatePrivateKey(
|
virtual CdmResponseType LoadCertificatePrivateKey(
|
||||||
const CryptoWrappedKey& private_key);
|
const CryptoWrappedKey& private_key);
|
||||||
virtual CdmResponseType GetBootCertificateChain(
|
virtual CdmResponseType GetBootCertificateChain(
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ class KeySession {
|
|||||||
typedef enum { kDefault, kEntitlement } KeySessionType;
|
typedef enum { kDefault, kEntitlement } KeySessionType;
|
||||||
virtual ~KeySession() {}
|
virtual ~KeySession() {}
|
||||||
virtual KeySessionType Type() = 0;
|
virtual KeySessionType Type() = 0;
|
||||||
virtual OEMCryptoResult GenerateDerivedKeys(const std::string& message) = 0;
|
|
||||||
virtual OEMCryptoResult GenerateDerivedKeys(
|
|
||||||
const std::string& message, const std::string& session_key) = 0;
|
|
||||||
virtual OEMCryptoResult LoadKeys(const std::string& message,
|
virtual OEMCryptoResult LoadKeys(const std::string& message,
|
||||||
const std::string& signature,
|
const std::string& signature,
|
||||||
const std::string& mac_key_iv,
|
const std::string& mac_key_iv,
|
||||||
|
|||||||
@@ -105,16 +105,18 @@ class CdmLicense {
|
|||||||
video_widevine::LicenseRequest* license_request);
|
video_widevine::LicenseRequest* license_request);
|
||||||
|
|
||||||
CdmResponseType HandleContentKeyResponse(
|
CdmResponseType HandleContentKeyResponse(
|
||||||
bool is_restore, const std::string& msg, const std::string& core_message,
|
bool is_restore, const std::string& session_key, const std::string& msg,
|
||||||
const std::string& signature, const std::vector<CryptoKey>& key_array,
|
const std::string& core_message, const std::string& signature,
|
||||||
|
const std::vector<CryptoKey>& key_array,
|
||||||
const video_widevine::License& license);
|
const video_widevine::License& license);
|
||||||
|
|
||||||
// HandleEntitlementKeyResponse loads the entitlement keys in |key_array| into
|
// HandleEntitlementKeyResponse loads the entitlement keys in |key_array| into
|
||||||
// the crypto session. In addition, it also extracts content keys from
|
// the crypto session. In addition, it also extracts content keys from
|
||||||
// |wrapped_keys_| and loads them for use.
|
// |wrapped_keys_| and loads them for use.
|
||||||
CdmResponseType HandleEntitlementKeyResponse(
|
CdmResponseType HandleEntitlementKeyResponse(
|
||||||
bool is_restore, const std::string& msg, const std::string& core_message,
|
bool is_restore, const std::string& session_key, const std::string& msg,
|
||||||
const std::string& signature, const std::vector<CryptoKey>& key_array,
|
const std::string& core_message, const std::string& signature,
|
||||||
|
const std::vector<CryptoKey>& key_array,
|
||||||
const video_widevine::License& license);
|
const video_widevine::License& license);
|
||||||
|
|
||||||
// Prepare to reload a key update message. Some special code is needed to work
|
// Prepare to reload a key update message. Some special code is needed to work
|
||||||
|
|||||||
@@ -261,6 +261,7 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequestInternal(
|
|||||||
status = crypto_session_->PrepareAndSignProvisioningRequest(
|
status = crypto_session_->PrepareAndSignProvisioningRequest(
|
||||||
serialized_message, &core_message, &request_signature,
|
serialized_message, &core_message, &request_signature,
|
||||||
should_specify_algorithm, oec_algorithm);
|
should_specify_algorithm, oec_algorithm);
|
||||||
|
request_ = serialized_message;
|
||||||
|
|
||||||
if (status != NO_ERROR) {
|
if (status != NO_ERROR) {
|
||||||
LOGE("Failed to prepare provisioning request: status = %d",
|
LOGE("Failed to prepare provisioning request: status = %d",
|
||||||
@@ -488,6 +489,7 @@ CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal(
|
|||||||
} else {
|
} else {
|
||||||
*request = std::move(serialized_request);
|
*request = std::move(serialized_request);
|
||||||
}
|
}
|
||||||
|
request_ = serialized_message;
|
||||||
return CdmResponseType(NO_ERROR);
|
return CdmResponseType(NO_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,20 +576,14 @@ CdmResponseType CertificateProvisioning::HandleProvisioning40Response(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = crypto_session_->GenerateDerivedKeys(
|
|
||||||
provisioning_request_message_, signed_response.session_key());
|
|
||||||
if (status != NO_ERROR) {
|
|
||||||
LOGE("Failed to generate derived keys.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get wrapped private key for cast cert
|
// Get wrapped private key for cast cert
|
||||||
CryptoWrappedKey cast_cert_private_key;
|
CryptoWrappedKey cast_cert_private_key;
|
||||||
const std::string& signature = signed_response.signature();
|
const std::string& signature = signed_response.signature();
|
||||||
const std::string& core_message = signed_response.oemcrypto_core_message();
|
const std::string& core_message = signed_response.oemcrypto_core_message();
|
||||||
status = crypto_session_->LoadProvisioning(response_message, core_message,
|
status = crypto_session_->LoadProvisioningCast(
|
||||||
signature,
|
signed_response.session_key(), provisioning_request_message_,
|
||||||
&cast_cert_private_key.key());
|
response_message, core_message, signature,
|
||||||
|
&cast_cert_private_key.key());
|
||||||
if (status != NO_ERROR) {
|
if (status != NO_ERROR) {
|
||||||
LOGE("Failed to generate wrapped key for cast cert.");
|
LOGE("Failed to generate wrapped key for cast cert.");
|
||||||
return status;
|
return status;
|
||||||
@@ -728,7 +724,7 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
|
|||||||
|
|
||||||
CryptoWrappedKey private_key;
|
CryptoWrappedKey private_key;
|
||||||
const CdmResponseType status = crypto_session_->LoadProvisioning(
|
const CdmResponseType status = crypto_session_->LoadProvisioning(
|
||||||
signed_message, core_message, signature, &private_key.key());
|
request_, signed_message, core_message, signature, &private_key.key());
|
||||||
|
|
||||||
if (status != NO_ERROR) {
|
if (status != NO_ERROR) {
|
||||||
LOGE("LoadProvisioning failed: status = %d", static_cast<int>(status));
|
LOGE("LoadProvisioning failed: status = %d", static_cast<int>(status));
|
||||||
|
|||||||
@@ -11,59 +11,6 @@
|
|||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
|
|
||||||
// Generate Derived Keys for ContentKeySession
|
|
||||||
OEMCryptoResult ContentKeySession::GenerateDerivedKeys(
|
|
||||||
const std::string& message) {
|
|
||||||
std::string mac_deriv_message;
|
|
||||||
std::string enc_deriv_message;
|
|
||||||
GenerateMacContext(message, &mac_deriv_message);
|
|
||||||
GenerateEncryptContext(message, &enc_deriv_message);
|
|
||||||
|
|
||||||
LOGV("Generating derived keys: id = %u", oec_session_id_);
|
|
||||||
OEMCryptoResult sts;
|
|
||||||
M_TIME(sts = OEMCrypto_GenerateDerivedKeys(
|
|
||||||
oec_session_id_,
|
|
||||||
reinterpret_cast<const uint8_t*>(mac_deriv_message.data()),
|
|
||||||
mac_deriv_message.size(),
|
|
||||||
reinterpret_cast<const uint8_t*>(enc_deriv_message.data()),
|
|
||||||
enc_deriv_message.size()),
|
|
||||||
metrics_, oemcrypto_generate_derived_keys_, sts);
|
|
||||||
if (OEMCrypto_SUCCESS != sts) {
|
|
||||||
LOGE("OEMCrypto_GenerateDerivedKeys failed: status = %d",
|
|
||||||
static_cast<int>(sts));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sts;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate Derived Keys (from session key) for ContentKeySession
|
|
||||||
OEMCryptoResult ContentKeySession::GenerateDerivedKeys(
|
|
||||||
const std::string& message, const std::string& session_key) {
|
|
||||||
std::string mac_deriv_message;
|
|
||||||
std::string enc_deriv_message;
|
|
||||||
GenerateMacContext(message, &mac_deriv_message);
|
|
||||||
GenerateEncryptContext(message, &enc_deriv_message);
|
|
||||||
|
|
||||||
LOGV("Generating derived keys from session key: id = %u", oec_session_id_);
|
|
||||||
OEMCryptoResult sts;
|
|
||||||
M_TIME(
|
|
||||||
sts = OEMCrypto_DeriveKeysFromSessionKey(
|
|
||||||
oec_session_id_, reinterpret_cast<const uint8_t*>(session_key.data()),
|
|
||||||
session_key.size(),
|
|
||||||
reinterpret_cast<const uint8_t*>(mac_deriv_message.data()),
|
|
||||||
mac_deriv_message.size(),
|
|
||||||
reinterpret_cast<const uint8_t*>(enc_deriv_message.data()),
|
|
||||||
enc_deriv_message.size()),
|
|
||||||
metrics_, oemcrypto_derive_keys_from_session_key_, sts);
|
|
||||||
|
|
||||||
if (OEMCrypto_SUCCESS != sts) {
|
|
||||||
LOGE("OEMCrypto_DeriveKeysFromSessionKey failed: status = %d",
|
|
||||||
static_cast<int>(sts));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sts;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load Keys for ContentKeySession
|
// Load Keys for ContentKeySession
|
||||||
OEMCryptoResult ContentKeySession::LoadKeys(
|
OEMCryptoResult ContentKeySession::LoadKeys(
|
||||||
const std::string& message, const std::string& signature,
|
const std::string& message, const std::string& signature,
|
||||||
|
|||||||
@@ -257,38 +257,6 @@ OEMCrypto_Substring GetSubstring(const std::string& message,
|
|||||||
return substring;
|
return substring;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateMacContext(const std::string& input_context,
|
|
||||||
std::string* deriv_context) {
|
|
||||||
if (!deriv_context) {
|
|
||||||
LOGE("Output parameter |deriv_context| not provided");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string kSigningKeyLabel = "AUTHENTICATION";
|
|
||||||
const size_t kSigningKeySizeBits = wvcdm::MAC_KEY_SIZE * 8;
|
|
||||||
|
|
||||||
deriv_context->assign(kSigningKeyLabel);
|
|
||||||
deriv_context->append(1, '\0');
|
|
||||||
deriv_context->append(input_context);
|
|
||||||
deriv_context->append(wvutil::EncodeUint32(kSigningKeySizeBits * 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GenerateEncryptContext(const std::string& input_context,
|
|
||||||
std::string* deriv_context) {
|
|
||||||
if (!deriv_context) {
|
|
||||||
LOGE("Output parameter |deriv_context| not provided");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string kEncryptionKeyLabel = "ENCRYPTION";
|
|
||||||
const size_t kEncryptionKeySizeBits = wvcdm::CONTENT_KEY_SIZE * 8;
|
|
||||||
|
|
||||||
deriv_context->assign(kEncryptionKeyLabel);
|
|
||||||
deriv_context->append(1, '\0');
|
|
||||||
deriv_context->append(input_context);
|
|
||||||
deriv_context->append(wvutil::EncodeUint32(kEncryptionKeySizeBits));
|
|
||||||
}
|
|
||||||
|
|
||||||
OEMCryptoCipherMode ToOEMCryptoCipherMode(CdmCipherMode cipher_mode) {
|
OEMCryptoCipherMode ToOEMCryptoCipherMode(CdmCipherMode cipher_mode) {
|
||||||
return cipher_mode == kCipherModeCtr ? OEMCrypto_CipherMode_CENC
|
return cipher_mode == kCipherModeCtr ? OEMCrypto_CipherMode_CENC
|
||||||
: OEMCrypto_CipherMode_CBCS;
|
: OEMCrypto_CipherMode_CBCS;
|
||||||
@@ -1122,7 +1090,9 @@ CdmResponseType CryptoSession::UseSecondaryKey(bool /* dual_key */) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CdmResponseType CryptoSession::LoadLicense(const std::string& signed_message,
|
CdmResponseType CryptoSession::LoadLicense(const std::string& context,
|
||||||
|
const std::string& session_key,
|
||||||
|
const std::string& signed_message,
|
||||||
const std::string& core_message,
|
const std::string& core_message,
|
||||||
const std::string& signature,
|
const std::string& signature,
|
||||||
CdmLicenseKeyType key_type) {
|
CdmLicenseKeyType key_type) {
|
||||||
@@ -1138,6 +1108,9 @@ CdmResponseType CryptoSession::LoadLicense(const std::string& signed_message,
|
|||||||
|
|
||||||
M_TIME(sts = OEMCrypto_LoadLicense(
|
M_TIME(sts = OEMCrypto_LoadLicense(
|
||||||
oec_session_id_,
|
oec_session_id_,
|
||||||
|
reinterpret_cast<const uint8_t*>(context.data()), context.size(),
|
||||||
|
reinterpret_cast<const uint8_t*>(session_key.data()),
|
||||||
|
session_key.size(),
|
||||||
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
||||||
combined_message.size(), core_message.size(),
|
combined_message.size(), core_message.size(),
|
||||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||||
@@ -1264,8 +1237,6 @@ CdmResponseType CryptoSession::PrepareAndSignProvisioningRequest(
|
|||||||
OEMCryptoResult sts;
|
OEMCryptoResult sts;
|
||||||
if (pre_provision_token_type_ == kClientTokenKeybox) {
|
if (pre_provision_token_type_ == kClientTokenKeybox) {
|
||||||
should_specify_algorithm = false;
|
should_specify_algorithm = false;
|
||||||
const CdmResponseType status = GenerateDerivedKeys(message);
|
|
||||||
if (status != NO_ERROR) return status;
|
|
||||||
} else if (pre_provision_token_type_ == kClientTokenOemCert) {
|
} else if (pre_provision_token_type_ == kClientTokenOemCert) {
|
||||||
should_specify_algorithm = true;
|
should_specify_algorithm = true;
|
||||||
WithOecSessionLock("LoadOEMPrivateKey", [&] {
|
WithOecSessionLock("LoadOEMPrivateKey", [&] {
|
||||||
@@ -1708,26 +1679,6 @@ CdmResponseType CryptoSession::SelectKey(const std::string& key_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CryptoSession::GenerateDerivedKeys(const std::string& message) {
|
|
||||||
OEMCryptoResult sts;
|
|
||||||
WithOecSessionLock("GenerateDerivedKeys without session_key",
|
|
||||||
[&] { sts = key_session_->GenerateDerivedKeys(message); });
|
|
||||||
|
|
||||||
return MapOEMCryptoResult(sts, GENERATE_DERIVED_KEYS_ERROR_2,
|
|
||||||
"GenerateDerivedKeys");
|
|
||||||
}
|
|
||||||
|
|
||||||
CdmResponseType CryptoSession::GenerateDerivedKeys(
|
|
||||||
const std::string& message, const std::string& session_key) {
|
|
||||||
OEMCryptoResult sts;
|
|
||||||
WithOecSessionLock("GenerateDerivedKeys with session_key", [&] {
|
|
||||||
sts = key_session_->GenerateDerivedKeys(message, session_key);
|
|
||||||
});
|
|
||||||
|
|
||||||
return MapOEMCryptoResult(sts, GENERATE_DERIVED_KEYS_ERROR,
|
|
||||||
"GenerateDerivedKeys");
|
|
||||||
}
|
|
||||||
|
|
||||||
CdmResponseType CryptoSession::GenerateRsaSignature(const std::string& message,
|
CdmResponseType CryptoSession::GenerateRsaSignature(const std::string& message,
|
||||||
std::string* signature,
|
std::string* signature,
|
||||||
RSA_Padding_Scheme scheme) {
|
RSA_Padding_Scheme scheme) {
|
||||||
@@ -2209,8 +2160,9 @@ bool CryptoSession::SetDestinationBufferType() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CryptoSession::LoadProvisioning(
|
CdmResponseType CryptoSession::LoadProvisioning(
|
||||||
const std::string& signed_message, const std::string& core_message,
|
const std::string& request, const std::string& signed_message,
|
||||||
const std::string& signature, std::string* wrapped_private_key) {
|
const std::string& core_message, const std::string& signature,
|
||||||
|
std::string* wrapped_private_key) {
|
||||||
LOGV("Loading provisioning certificate: id = %u", oec_session_id_);
|
LOGV("Loading provisioning certificate: id = %u", oec_session_id_);
|
||||||
if (wrapped_private_key == nullptr) {
|
if (wrapped_private_key == nullptr) {
|
||||||
LOGE("Missing wrapped |wrapped_private_key|");
|
LOGE("Missing wrapped |wrapped_private_key|");
|
||||||
@@ -2224,6 +2176,7 @@ CdmResponseType CryptoSession::LoadProvisioning(
|
|||||||
WithOecSessionLock("LoadProvisioning Attempt 1", [&] {
|
WithOecSessionLock("LoadProvisioning Attempt 1", [&] {
|
||||||
M_TIME(status = OEMCrypto_LoadProvisioning(
|
M_TIME(status = OEMCrypto_LoadProvisioning(
|
||||||
oec_session_id_,
|
oec_session_id_,
|
||||||
|
reinterpret_cast<const uint8_t*>(request.data()), request.size(),
|
||||||
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
||||||
combined_message.size(), core_message.size(),
|
combined_message.size(), core_message.size(),
|
||||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||||
@@ -2241,6 +2194,7 @@ CdmResponseType CryptoSession::LoadProvisioning(
|
|||||||
WithOecSessionLock("LoadProvisioning Attempt 2", [&] {
|
WithOecSessionLock("LoadProvisioning Attempt 2", [&] {
|
||||||
M_TIME(status = OEMCrypto_LoadProvisioning(
|
M_TIME(status = OEMCrypto_LoadProvisioning(
|
||||||
oec_session_id_,
|
oec_session_id_,
|
||||||
|
reinterpret_cast<const uint8_t*>(request.data()), request.size(),
|
||||||
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
||||||
combined_message.size(), core_message.size(),
|
combined_message.size(), core_message.size(),
|
||||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||||
@@ -2259,6 +2213,64 @@ CdmResponseType CryptoSession::LoadProvisioning(
|
|||||||
"LoadProvisioning");
|
"LoadProvisioning");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CdmResponseType CryptoSession::LoadProvisioningCast(
|
||||||
|
const std::string& derivation_key, const std::string& request,
|
||||||
|
const std::string& signed_message, const std::string& core_message,
|
||||||
|
const std::string& signature, std::string* wrapped_private_key) {
|
||||||
|
LOGV("Loading provisioning certificate: id = %u", oec_session_id_);
|
||||||
|
if (wrapped_private_key == nullptr) {
|
||||||
|
LOGE("Missing wrapped |wrapped_private_key|");
|
||||||
|
return CdmResponseType(PARAMETER_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string combined_message = core_message + signed_message;
|
||||||
|
// Round 1, get the size of the wrapped private key buffer.
|
||||||
|
size_t wrapped_private_key_length = 0;
|
||||||
|
OEMCryptoResult status;
|
||||||
|
WithOecSessionLock("LoadProvisioningCast Attempt 1", [&] {
|
||||||
|
M_TIME(status = OEMCrypto_LoadProvisioningCast(
|
||||||
|
oec_session_id_,
|
||||||
|
reinterpret_cast<const uint8_t*>(derivation_key.data()),
|
||||||
|
derivation_key.size(),
|
||||||
|
reinterpret_cast<const uint8_t*>(request.data()), request.size(),
|
||||||
|
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
||||||
|
combined_message.size(), core_message.size(),
|
||||||
|
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||||
|
signature.size(), nullptr, &wrapped_private_key_length),
|
||||||
|
metrics_, oemcrypto_load_provisioning_, status);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status != OEMCrypto_ERROR_SHORT_BUFFER) {
|
||||||
|
return MapOEMCryptoResult(status, LOAD_PROVISIONING_ERROR,
|
||||||
|
"LoadProvisioningCast");
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapped_private_key->resize(wrapped_private_key_length);
|
||||||
|
|
||||||
|
WithOecSessionLock("LoadProvisioningCast Attempt 2", [&] {
|
||||||
|
M_TIME(status = OEMCrypto_LoadProvisioningCast(
|
||||||
|
oec_session_id_,
|
||||||
|
reinterpret_cast<const uint8_t*>(derivation_key.data()),
|
||||||
|
derivation_key.size(),
|
||||||
|
reinterpret_cast<const uint8_t*>(request.data()), request.size(),
|
||||||
|
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
||||||
|
combined_message.size(), core_message.size(),
|
||||||
|
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||||
|
signature.size(),
|
||||||
|
reinterpret_cast<uint8_t*>(&wrapped_private_key->front()),
|
||||||
|
&wrapped_private_key_length),
|
||||||
|
metrics_, oemcrypto_load_provisioning_, status);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status == OEMCrypto_SUCCESS) {
|
||||||
|
wrapped_private_key->resize(wrapped_private_key_length);
|
||||||
|
return CdmResponseType(NO_ERROR);
|
||||||
|
}
|
||||||
|
wrapped_private_key->clear();
|
||||||
|
return MapOEMCryptoResult(status, LOAD_PROVISIONING_ERROR,
|
||||||
|
"LoadProvisioningCast");
|
||||||
|
}
|
||||||
|
|
||||||
CdmResponseType CryptoSession::GetHdcpCapabilities(HdcpCapability* current,
|
CdmResponseType CryptoSession::GetHdcpCapabilities(HdcpCapability* current,
|
||||||
HdcpCapability* max) {
|
HdcpCapability* max) {
|
||||||
LOGV("Getting HDCP capabilities: id = %u", oec_session_id_);
|
LOGV("Getting HDCP capabilities: id = %u", oec_session_id_);
|
||||||
|
|||||||
@@ -585,10 +585,6 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
|||||||
LOGE("Signed response has no session keys present");
|
LOGE("Signed response has no session keys present");
|
||||||
return CdmResponseType(SESSION_KEYS_NOT_FOUND);
|
return CdmResponseType(SESSION_KEYS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
CdmResponseType status = crypto_session_->GenerateDerivedKeys(
|
|
||||||
key_request_, signed_response.session_key());
|
|
||||||
|
|
||||||
if (status != NO_ERROR) return status;
|
|
||||||
|
|
||||||
// Extract mac key
|
// Extract mac key
|
||||||
std::string mac_key_iv;
|
std::string mac_key_iv;
|
||||||
@@ -655,18 +651,19 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the field is not set, it will default to false.
|
// If the field is not set, it will default to false.
|
||||||
status =
|
CdmResponseType status =
|
||||||
crypto_session_->UseSecondaryKey(signed_response.using_secondary_key());
|
crypto_session_->UseSecondaryKey(signed_response.using_secondary_key());
|
||||||
if (status != NO_ERROR) return status;
|
if (status != NO_ERROR) return status;
|
||||||
|
|
||||||
CdmResponseType resp(NO_CONTENT_KEY);
|
CdmResponseType resp(NO_CONTENT_KEY);
|
||||||
if (kLicenseKeyTypeEntitlement == key_type) {
|
if (kLicenseKeyTypeEntitlement == key_type) {
|
||||||
resp =
|
resp = HandleEntitlementKeyResponse(
|
||||||
HandleEntitlementKeyResponse(is_restore, signed_message, core_message,
|
is_restore, signed_response.session_key(), signed_message, core_message,
|
||||||
signature, key_array, license);
|
signature, key_array, license);
|
||||||
} else if (kLicenseKeyTypeContent == key_type) {
|
} else if (kLicenseKeyTypeContent == key_type) {
|
||||||
resp = HandleContentKeyResponse(is_restore, signed_message, core_message,
|
resp = HandleContentKeyResponse(is_restore, signed_response.session_key(),
|
||||||
signature, key_array, license);
|
signed_message, core_message, signature,
|
||||||
|
key_array, license);
|
||||||
}
|
}
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
@@ -1086,15 +1083,17 @@ CdmResponseType CdmLicense::PrepareContentId(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CdmLicense::HandleContentKeyResponse(
|
CdmResponseType CdmLicense::HandleContentKeyResponse(
|
||||||
bool is_restore, const std::string& msg, const std::string& core_message,
|
bool is_restore, const std::string& session_key, const std::string& msg,
|
||||||
const std::string& signature, const std::vector<CryptoKey>& key_array,
|
const std::string& core_message, const std::string& signature,
|
||||||
|
const std::vector<CryptoKey>& key_array,
|
||||||
const video_widevine::License& license) {
|
const video_widevine::License& license) {
|
||||||
if (key_array.empty()) {
|
if (key_array.empty()) {
|
||||||
LOGE("No content keys provided");
|
LOGE("No content keys provided");
|
||||||
return CdmResponseType(NO_CONTENT_KEY);
|
return CdmResponseType(NO_CONTENT_KEY);
|
||||||
}
|
}
|
||||||
const CdmResponseType resp = crypto_session_->LoadLicense(
|
const CdmResponseType resp =
|
||||||
msg, core_message, signature, kLicenseKeyTypeContent);
|
crypto_session_->LoadLicense(key_request_, session_key, msg, core_message,
|
||||||
|
signature, kLicenseKeyTypeContent);
|
||||||
if (KEY_ADDED == resp) {
|
if (KEY_ADDED == resp) {
|
||||||
loaded_keys_.clear();
|
loaded_keys_.clear();
|
||||||
for (const CryptoKey& key : key_array) {
|
for (const CryptoKey& key : key_array) {
|
||||||
@@ -1106,15 +1105,17 @@ CdmResponseType CdmLicense::HandleContentKeyResponse(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CdmLicense::HandleEntitlementKeyResponse(
|
CdmResponseType CdmLicense::HandleEntitlementKeyResponse(
|
||||||
bool is_restore, const std::string& msg, const std::string& core_message,
|
bool is_restore, const std::string& session_key, const std::string& msg,
|
||||||
const std::string& signature, const std::vector<CryptoKey>& key_array,
|
const std::string& core_message, const std::string& signature,
|
||||||
|
const std::vector<CryptoKey>& key_array,
|
||||||
const video_widevine::License& license) {
|
const video_widevine::License& license) {
|
||||||
if (key_array.empty()) {
|
if (key_array.empty()) {
|
||||||
LOGE("No entitlement keys provided");
|
LOGE("No entitlement keys provided");
|
||||||
return CdmResponseType(NO_CONTENT_KEY);
|
return CdmResponseType(NO_CONTENT_KEY);
|
||||||
}
|
}
|
||||||
const CdmResponseType resp = crypto_session_->LoadLicense(
|
const CdmResponseType resp =
|
||||||
msg, core_message, signature, kLicenseKeyTypeEntitlement);
|
crypto_session_->LoadLicense(key_request_, session_key, msg, core_message,
|
||||||
|
signature, kLicenseKeyTypeEntitlement);
|
||||||
|
|
||||||
if (KEY_ADDED != resp) {
|
if (KEY_ADDED != resp) {
|
||||||
return resp;
|
return resp;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "metrics_collections.h"
|
#include "metrics_collections.h"
|
||||||
#include "odk_structs.h"
|
#include "odk_structs.h"
|
||||||
|
#include "platform.h"
|
||||||
#include "properties.h"
|
#include "properties.h"
|
||||||
#include "wv_cdm_constants.h"
|
#include "wv_cdm_constants.h"
|
||||||
#include "wv_cdm_types.h"
|
#include "wv_cdm_types.h"
|
||||||
@@ -56,7 +57,7 @@ typedef OEMCryptoResult (*L1_SetMaxAPIVersion_t)(uint32_t max_version);
|
|||||||
typedef OEMCryptoResult (*L1_Terminate_t)(void);
|
typedef OEMCryptoResult (*L1_Terminate_t)(void);
|
||||||
typedef OEMCryptoResult (*L1_OpenSession_t)(OEMCrypto_SESSION* session);
|
typedef OEMCryptoResult (*L1_OpenSession_t)(OEMCrypto_SESSION* session);
|
||||||
typedef OEMCryptoResult (*L1_CloseSession_t)(OEMCrypto_SESSION session);
|
typedef OEMCryptoResult (*L1_CloseSession_t)(OEMCrypto_SESSION session);
|
||||||
typedef OEMCryptoResult (*L1_GenerateDerivedKeys_t)(
|
typedef OEMCryptoResult (*L1_GenerateDerivedKeys_V18_t)(
|
||||||
OEMCrypto_SESSION session, const uint8_t* mac_key_context,
|
OEMCrypto_SESSION session, const uint8_t* mac_key_context,
|
||||||
size_t mac_key_context_length, const uint8_t* enc_key_context,
|
size_t mac_key_context_length, const uint8_t* enc_key_context,
|
||||||
size_t enc_key_context_length);
|
size_t enc_key_context_length);
|
||||||
@@ -76,12 +77,17 @@ typedef OEMCryptoResult (*L1_PrepAndSignRenewalRequest_t)(
|
|||||||
typedef OEMCryptoResult (*L1_PrepAndSignProvisioningRequest_t)(
|
typedef OEMCryptoResult (*L1_PrepAndSignProvisioningRequest_t)(
|
||||||
OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
|
OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
|
||||||
size_t* core_message_length, uint8_t* signature, size_t* signature_length);
|
size_t* core_message_length, uint8_t* signature, size_t* signature_length);
|
||||||
typedef OEMCryptoResult (*L1_LoadLicense_t)(OEMCrypto_SESSION session,
|
typedef OEMCryptoResult (*L1_LoadLicense_t)(
|
||||||
const uint8_t* message,
|
OEMCrypto_SESSION session, const uint8_t* context, size_t context_length,
|
||||||
size_t message_length,
|
const uint8_t* derivation_key, size_t derivation_key_length,
|
||||||
size_t core_message_length,
|
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||||
const uint8_t* signature,
|
const uint8_t* signature, size_t signature_length);
|
||||||
size_t signature_length);
|
typedef OEMCryptoResult (*L1_LoadLicense_V18_t)(OEMCrypto_SESSION session,
|
||||||
|
const uint8_t* message,
|
||||||
|
size_t message_length,
|
||||||
|
size_t core_message_length,
|
||||||
|
const uint8_t* signature,
|
||||||
|
size_t signature_length);
|
||||||
typedef OEMCryptoResult (*L1_LoadEntitledContentKeys_t)(
|
typedef OEMCryptoResult (*L1_LoadEntitledContentKeys_t)(
|
||||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||||
size_t key_array_length,
|
size_t key_array_length,
|
||||||
@@ -144,7 +150,7 @@ typedef OEMCryptoResult (*L1_GenerateRSASignature_t)(
|
|||||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||||
uint8_t* signature, size_t* signature_length,
|
uint8_t* signature, size_t* signature_length,
|
||||||
RSA_Padding_Scheme padding_scheme);
|
RSA_Padding_Scheme padding_scheme);
|
||||||
typedef OEMCryptoResult (*L1_DeriveKeysFromSessionKey_t)(
|
typedef OEMCryptoResult (*L1_DeriveKeysFromSessionKey_V18_t)(
|
||||||
OEMCrypto_SESSION session, const uint8_t* enc_session_key,
|
OEMCrypto_SESSION session, const uint8_t* enc_session_key,
|
||||||
size_t enc_session_key_length, const uint8_t* mac_key_context,
|
size_t enc_session_key_length, const uint8_t* mac_key_context,
|
||||||
size_t mac_key_context_length, const uint8_t* enc_key_context,
|
size_t mac_key_context_length, const uint8_t* enc_key_context,
|
||||||
@@ -226,6 +232,17 @@ typedef OEMCryptoResult (*L1_FreeSecureBuffer_t)(
|
|||||||
int secure_fd);
|
int secure_fd);
|
||||||
typedef size_t (*L1_MaximumUsageTableHeaderSize_t)();
|
typedef size_t (*L1_MaximumUsageTableHeaderSize_t)();
|
||||||
typedef OEMCryptoResult (*L1_LoadProvisioning_t)(
|
typedef OEMCryptoResult (*L1_LoadProvisioning_t)(
|
||||||
|
OEMCrypto_SESSION session, const uint8_t* request, size_t request_length,
|
||||||
|
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||||
|
const uint8_t* signature, size_t signature_length,
|
||||||
|
uint8_t* wrapped_private_key, size_t* wrapped_private_key_length);
|
||||||
|
typedef OEMCryptoResult (*L1_LoadProvisioningCast_t)(
|
||||||
|
OEMCrypto_SESSION session, const uint8_t* derivation_key,
|
||||||
|
size_t derivation_key_length, const uint8_t* request, size_t request_length,
|
||||||
|
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||||
|
const uint8_t* signature, size_t signature_length,
|
||||||
|
uint8_t* wrapped_private_key, size_t* wrapped_private_key_length);
|
||||||
|
typedef OEMCryptoResult (*L1_LoadProvisioning_V18_t)(
|
||||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||||
size_t core_message_length, const uint8_t* signature,
|
size_t core_message_length, const uint8_t* signature,
|
||||||
size_t signature_length, uint8_t* wrapped_private_key,
|
size_t signature_length, uint8_t* wrapped_private_key,
|
||||||
@@ -328,13 +345,14 @@ struct FunctionPointers {
|
|||||||
L1_Terminate_t Terminate;
|
L1_Terminate_t Terminate;
|
||||||
L1_OpenSession_t OpenSession;
|
L1_OpenSession_t OpenSession;
|
||||||
L1_CloseSession_t CloseSession;
|
L1_CloseSession_t CloseSession;
|
||||||
L1_GenerateDerivedKeys_t GenerateDerivedKeys;
|
L1_GenerateDerivedKeys_V18_t GenerateDerivedKeys_V18;
|
||||||
L1_GenerateNonce_t GenerateNonce;
|
L1_GenerateNonce_t GenerateNonce;
|
||||||
L1_GenerateSignature_t GenerateSignature;
|
L1_GenerateSignature_t GenerateSignature;
|
||||||
L1_PrepAndSignLicenseRequest_t PrepAndSignLicenseRequest;
|
L1_PrepAndSignLicenseRequest_t PrepAndSignLicenseRequest;
|
||||||
L1_PrepAndSignRenewalRequest_t PrepAndSignRenewalRequest;
|
L1_PrepAndSignRenewalRequest_t PrepAndSignRenewalRequest;
|
||||||
L1_PrepAndSignProvisioningRequest_t PrepAndSignProvisioningRequest;
|
L1_PrepAndSignProvisioningRequest_t PrepAndSignProvisioningRequest;
|
||||||
L1_LoadLicense_t LoadLicense;
|
L1_LoadLicense_t LoadLicense;
|
||||||
|
L1_LoadLicense_V18_t LoadLicense_V18;
|
||||||
L1_LoadEntitledContentKeys_t LoadEntitledContentKeys;
|
L1_LoadEntitledContentKeys_t LoadEntitledContentKeys;
|
||||||
L1_LoadEntitledContentKeys_V16_t LoadEntitledContentKeys_V16;
|
L1_LoadEntitledContentKeys_V16_t LoadEntitledContentKeys_V16;
|
||||||
L1_LoadRenewal_t LoadRenewal;
|
L1_LoadRenewal_t LoadRenewal;
|
||||||
@@ -354,7 +372,7 @@ struct FunctionPointers {
|
|||||||
L1_LoadDRMPrivateKey_t LoadDRMPrivateKey;
|
L1_LoadDRMPrivateKey_t LoadDRMPrivateKey;
|
||||||
L1_LoadTestRSAKey_t LoadTestRSAKey;
|
L1_LoadTestRSAKey_t LoadTestRSAKey;
|
||||||
L1_GenerateRSASignature_t GenerateRSASignature;
|
L1_GenerateRSASignature_t GenerateRSASignature;
|
||||||
L1_DeriveKeysFromSessionKey_t DeriveKeysFromSessionKey;
|
L1_DeriveKeysFromSessionKey_V18_t DeriveKeysFromSessionKey_V18;
|
||||||
L1_APIVersion_t APIVersion;
|
L1_APIVersion_t APIVersion;
|
||||||
L1_SecurityPatchLevel_t SecurityPatchLevel;
|
L1_SecurityPatchLevel_t SecurityPatchLevel;
|
||||||
L1_SecurityLevel_V16_t SecurityLevel_V16;
|
L1_SecurityLevel_V16_t SecurityLevel_V16;
|
||||||
@@ -392,6 +410,8 @@ struct FunctionPointers {
|
|||||||
L1_FreeSecureBuffer_t FreeSecureBuffer;
|
L1_FreeSecureBuffer_t FreeSecureBuffer;
|
||||||
L1_MaximumUsageTableHeaderSize_t MaximumUsageTableHeaderSize;
|
L1_MaximumUsageTableHeaderSize_t MaximumUsageTableHeaderSize;
|
||||||
L1_LoadProvisioning_t LoadProvisioning;
|
L1_LoadProvisioning_t LoadProvisioning;
|
||||||
|
L1_LoadProvisioningCast_t LoadProvisioningCast;
|
||||||
|
L1_LoadProvisioning_V18_t LoadProvisioning_V18;
|
||||||
L1_MinorAPIVersion_t MinorAPIVersion;
|
L1_MinorAPIVersion_t MinorAPIVersion;
|
||||||
L1_OPK_SerializationVersion_t OPK_SerializationVersion;
|
L1_OPK_SerializationVersion_t OPK_SerializationVersion;
|
||||||
L1_CreateEntitledKeySession_t CreateEntitledKeySession;
|
L1_CreateEntitledKeySession_t CreateEntitledKeySession;
|
||||||
@@ -950,8 +970,8 @@ class Adapter {
|
|||||||
LOOKUP_ALL(13, CreateUsageTableHeader, OEMCrypto_CreateUsageTableHeader);
|
LOOKUP_ALL(13, CreateUsageTableHeader, OEMCrypto_CreateUsageTableHeader);
|
||||||
LOOKUP_ALL(13, DeactivateUsageEntry, OEMCrypto_DeactivateUsageEntry);
|
LOOKUP_ALL(13, DeactivateUsageEntry, OEMCrypto_DeactivateUsageEntry);
|
||||||
LOOKUP_ALL(16, DecryptCENC_V17, OEMCrypto_DecryptCENC_V17);
|
LOOKUP_ALL(16, DecryptCENC_V17, OEMCrypto_DecryptCENC_V17);
|
||||||
LOOKUP_ALL( 8, DeriveKeysFromSessionKey, OEMCrypto_DeriveKeysFromSessionKey);
|
LOOKUP_ALL( 8, DeriveKeysFromSessionKey_V18, OEMCrypto_DeriveKeysFromSessionKey_V18);
|
||||||
LOOKUP_ALL(16, GenerateDerivedKeys, OEMCrypto_GenerateDerivedKeys);
|
LOOKUP_ALL(16, GenerateDerivedKeys_V18, OEMCrypto_GenerateDerivedKeys_V18);
|
||||||
LOOKUP_ALL( 8, GenerateNonce, OEMCrypto_GenerateNonce);
|
LOOKUP_ALL( 8, GenerateNonce, OEMCrypto_GenerateNonce);
|
||||||
LOOKUP_ALL( 9, GenerateRSASignature, OEMCrypto_GenerateRSASignature);
|
LOOKUP_ALL( 9, GenerateRSASignature, OEMCrypto_GenerateRSASignature);
|
||||||
LOOKUP( 8, 15, GenerateSignature, OEMCrypto_GenerateSignature);
|
LOOKUP( 8, 15, GenerateSignature, OEMCrypto_GenerateSignature);
|
||||||
@@ -981,7 +1001,8 @@ class Adapter {
|
|||||||
LOOKUP_ALL( 8, IsKeyboxOrOEMCertValid, OEMCrypto_IsKeyboxOrOEMCertValid);
|
LOOKUP_ALL( 8, IsKeyboxOrOEMCertValid, OEMCrypto_IsKeyboxOrOEMCertValid);
|
||||||
LOOKUP( 8, 15, LoadDeviceRSAKey, OEMCrypto_LoadDeviceRSAKey);
|
LOOKUP( 8, 15, LoadDeviceRSAKey, OEMCrypto_LoadDeviceRSAKey);
|
||||||
LOOKUP_ALL(16, LoadDRMPrivateKey, OEMCrypto_LoadDRMPrivateKey);
|
LOOKUP_ALL(16, LoadDRMPrivateKey, OEMCrypto_LoadDRMPrivateKey);
|
||||||
LOOKUP_ALL(16, LoadLicense, OEMCrypto_LoadLicense);
|
LOOKUP_ALL(19, LoadLicense, OEMCrypto_LoadLicense);
|
||||||
|
LOOKUP_ALL(16, LoadLicense_V18, OEMCrypto_LoadLicense_V18);
|
||||||
LOOKUP(15, 16, LoadEntitledContentKeys_V16,OEMCrypto_LoadEntitledContentKeys_V16);
|
LOOKUP(15, 16, LoadEntitledContentKeys_V16,OEMCrypto_LoadEntitledContentKeys_V16);
|
||||||
LOOKUP_ALL(17, LoadEntitledContentKeys, OEMCrypto_LoadEntitledContentKeys);
|
LOOKUP_ALL(17, LoadEntitledContentKeys, OEMCrypto_LoadEntitledContentKeys);
|
||||||
LOOKUP_ALL(14, LoadTestKeybox, OEMCrypto_LoadTestKeybox);
|
LOOKUP_ALL(14, LoadTestKeybox, OEMCrypto_LoadTestKeybox);
|
||||||
@@ -1008,7 +1029,9 @@ class Adapter {
|
|||||||
LOOKUP_ALL(16, AllocateSecureBuffer, OEMCrypto_AllocateSecureBuffer);
|
LOOKUP_ALL(16, AllocateSecureBuffer, OEMCrypto_AllocateSecureBuffer);
|
||||||
LOOKUP_ALL(16, FreeSecureBuffer, OEMCrypto_FreeSecureBuffer);
|
LOOKUP_ALL(16, FreeSecureBuffer, OEMCrypto_FreeSecureBuffer);
|
||||||
LOOKUP_ALL(16, MaximumUsageTableHeaderSize, OEMCrypto_MaximumUsageTableHeaderSize);
|
LOOKUP_ALL(16, MaximumUsageTableHeaderSize, OEMCrypto_MaximumUsageTableHeaderSize);
|
||||||
LOOKUP_ALL(16, LoadProvisioning, OEMCrypto_LoadProvisioning);
|
LOOKUP_ALL(16, LoadProvisioning_V18, OEMCrypto_LoadProvisioning_V18);
|
||||||
|
LOOKUP_ALL(19, LoadProvisioning, OEMCrypto_LoadProvisioning);
|
||||||
|
LOOKUP_ALL(19, LoadProvisioningCast, OEMCrypto_LoadProvisioningCast);
|
||||||
LOOKUP_ALL(16, MinorAPIVersion, OEMCrypto_MinorAPIVersion);
|
LOOKUP_ALL(16, MinorAPIVersion, OEMCrypto_MinorAPIVersion);
|
||||||
LOOKUP_ALL(16, OPK_SerializationVersion, OEMCrypto_OPK_SerializationVersion);
|
LOOKUP_ALL(16, OPK_SerializationVersion, OEMCrypto_OPK_SerializationVersion);
|
||||||
LOOKUP_ALL(17, CreateEntitledKeySession, OEMCrypto_CreateEntitledKeySession);
|
LOOKUP_ALL(17, CreateEntitledKeySession, OEMCrypto_CreateEntitledKeySession);
|
||||||
@@ -1077,9 +1100,9 @@ class Adapter {
|
|||||||
level3_.Terminate = Level3_Terminate;
|
level3_.Terminate = Level3_Terminate;
|
||||||
level3_.OpenSession = Level3_OpenSession;
|
level3_.OpenSession = Level3_OpenSession;
|
||||||
level3_.CloseSession = Level3_CloseSession;
|
level3_.CloseSession = Level3_CloseSession;
|
||||||
level3_.GenerateDerivedKeys = Level3_GenerateDerivedKeys;
|
level3_.GenerateDerivedKeys_V18 = Level3_GenerateDerivedKeys;
|
||||||
level3_.GenerateNonce = Level3_GenerateNonce;
|
level3_.GenerateNonce = Level3_GenerateNonce;
|
||||||
level3_.LoadLicense = Level3_LoadLicense;
|
level3_.LoadLicense_V18 = Level3_LoadLicense;
|
||||||
level3_.LoadEntitledContentKeys = Level3_LoadEntitledContentKeys;
|
level3_.LoadEntitledContentKeys = Level3_LoadEntitledContentKeys;
|
||||||
level3_.LoadRenewal = Level3_LoadRenewal;
|
level3_.LoadRenewal = Level3_LoadRenewal;
|
||||||
level3_.QueryKeyControl = Level3_QueryKeyControl;
|
level3_.QueryKeyControl = Level3_QueryKeyControl;
|
||||||
@@ -1097,7 +1120,7 @@ class Adapter {
|
|||||||
level3_.LoadOEMPrivateKey = Level3_LoadOEMPrivateKey;
|
level3_.LoadOEMPrivateKey = Level3_LoadOEMPrivateKey;
|
||||||
level3_.LoadTestRSAKey = Level3_LoadTestRSAKey;
|
level3_.LoadTestRSAKey = Level3_LoadTestRSAKey;
|
||||||
level3_.GenerateRSASignature = Level3_GenerateRSASignature;
|
level3_.GenerateRSASignature = Level3_GenerateRSASignature;
|
||||||
level3_.DeriveKeysFromSessionKey = Level3_DeriveKeysFromSessionKey;
|
level3_.DeriveKeysFromSessionKey_V18 = Level3_DeriveKeysFromSessionKey;
|
||||||
level3_.APIVersion = Level3_APIVersion;
|
level3_.APIVersion = Level3_APIVersion;
|
||||||
level3_.MinorAPIVersion = Level3_MinorAPIVersion;
|
level3_.MinorAPIVersion = Level3_MinorAPIVersion;
|
||||||
level3_.SecurityPatchLevel = Level3_SecurityPatchLevel;
|
level3_.SecurityPatchLevel = Level3_SecurityPatchLevel;
|
||||||
@@ -1130,7 +1153,7 @@ class Adapter {
|
|||||||
level3_.SupportsDecryptHash = Level3_SupportsDecryptHash;
|
level3_.SupportsDecryptHash = Level3_SupportsDecryptHash;
|
||||||
level3_.SetDecryptHash = Level3_SetDecryptHash;
|
level3_.SetDecryptHash = Level3_SetDecryptHash;
|
||||||
level3_.GetHashErrorCode = Level3_GetHashErrorCode;
|
level3_.GetHashErrorCode = Level3_GetHashErrorCode;
|
||||||
level3_.LoadProvisioning = Level3_LoadProvisioning;
|
level3_.LoadProvisioning_V18 = Level3_LoadProvisioning;
|
||||||
level3_.PrepAndSignProvisioningRequest = Level3_PrepAndSignProvisioningRequest;
|
level3_.PrepAndSignProvisioningRequest = Level3_PrepAndSignProvisioningRequest;
|
||||||
level3_.PrepAndSignLicenseRequest = Level3_PrepAndSignLicenseRequest;
|
level3_.PrepAndSignLicenseRequest = Level3_PrepAndSignLicenseRequest;
|
||||||
level3_.PrepAndSignRenewalRequest = Level3_PrepAndSignRenewalRequest;
|
level3_.PrepAndSignRenewalRequest = Level3_PrepAndSignRenewalRequest;
|
||||||
@@ -1160,6 +1183,9 @@ class Adapter {
|
|||||||
level3_.Generic_Verify = Level3_Generic_Verify;
|
level3_.Generic_Verify = Level3_Generic_Verify;
|
||||||
level3_.GetSignatureHashAlgorithm = nullptr;
|
level3_.GetSignatureHashAlgorithm = nullptr;
|
||||||
level3_.EnterTestMode = nullptr;
|
level3_.EnterTestMode = nullptr;
|
||||||
|
level3_.LoadLicense = nullptr;
|
||||||
|
level3_.LoadProvisioning = nullptr;
|
||||||
|
level3_.LoadProvisioningCast = nullptr;
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
level3_.version = Level3_APIVersion();
|
level3_.version = Level3_APIVersion();
|
||||||
@@ -1992,19 +2018,19 @@ extern "C" OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session) {
|
|||||||
return gAdapter->CloseSession(session);
|
return gAdapter->CloseSession(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_GenerateDerivedKeys(
|
extern "C" OEMCryptoResult OEMCrypto_GenerateDerivedKeys_V18(
|
||||||
OEMCrypto_SESSION session, const uint8_t* mac_key_context,
|
OEMCrypto_SESSION session, const uint8_t* mac_key_context,
|
||||||
size_t mac_key_context_length, const uint8_t* enc_key_context,
|
size_t mac_key_context_length, const uint8_t* enc_key_context,
|
||||||
size_t enc_key_context_length) {
|
size_t enc_key_context_length) {
|
||||||
if (!gAdapter.get()) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
if (!gAdapter.get()) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
LevelSession pair = gAdapter->GetSession(session);
|
LevelSession pair = gAdapter->GetSession(session);
|
||||||
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
if (pair.fcn->GenerateDerivedKeys == nullptr) {
|
if (pair.fcn->GenerateDerivedKeys_V18 == nullptr) {
|
||||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
return pair.fcn->GenerateDerivedKeys(pair.session, mac_key_context,
|
return pair.fcn->GenerateDerivedKeys_V18(
|
||||||
mac_key_context_length, enc_key_context,
|
pair.session, mac_key_context, mac_key_context_length, enc_key_context,
|
||||||
enc_key_context_length);
|
enc_key_context_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
|
extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
|
||||||
@@ -2087,20 +2113,49 @@ const uint8_t* PointerOrNull(const uint8_t* pointer, size_t length) {
|
|||||||
return length ? pointer : nullptr;
|
return length ? pointer : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_LoadLicense(OEMCrypto_SESSION session,
|
template <size_t N>
|
||||||
const uint8_t* message,
|
std::vector<uint8_t> MakeContext(const char (&key_label)[N],
|
||||||
size_t message_length,
|
const uint8_t* context, size_t context_length,
|
||||||
size_t core_message_length,
|
uint32_t suffix) {
|
||||||
const uint8_t* signature,
|
// TODO(b/299343035): Use ODK methods.
|
||||||
size_t signature_length) {
|
std::vector<uint8_t> ret;
|
||||||
|
ret.insert(ret.end(), key_label, key_label + N);
|
||||||
|
ret.insert(ret.end(), context, context + context_length);
|
||||||
|
const uint32_t suffix_net = htonl(suffix);
|
||||||
|
auto* ptr = reinterpret_cast<const uint8_t*>(&suffix_net);
|
||||||
|
ret.insert(ret.end(), ptr, ptr + sizeof(suffix_net));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" OEMCryptoResult OEMCrypto_LoadLicense(
|
||||||
|
OEMCrypto_SESSION session, const uint8_t* context, size_t context_length,
|
||||||
|
const uint8_t* derivation_key, size_t derivation_key_length,
|
||||||
|
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||||
|
const uint8_t* signature, size_t signature_length) {
|
||||||
if (!gAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
if (!gAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
LevelSession pair = gAdapter->GetSession(session);
|
LevelSession pair = gAdapter->GetSession(session);
|
||||||
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
if (pair.fcn->LoadLicense == nullptr) {
|
if (pair.fcn->LoadLicense == nullptr) {
|
||||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
if (pair.fcn->LoadLicense_V18 == nullptr ||
|
||||||
|
pair.fcn->DeriveKeysFromSessionKey_V18 == nullptr) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<uint8_t> mac_context =
|
||||||
|
MakeContext("AUTHENTICATION", context, context_length, 0x200);
|
||||||
|
const std::vector<uint8_t> enc_context =
|
||||||
|
MakeContext("ENCRYPTION", context, context_length, 0x80);
|
||||||
|
const OEMCryptoResult result = pair.fcn->DeriveKeysFromSessionKey_V18(
|
||||||
|
session, derivation_key, derivation_key_length, mac_context.data(),
|
||||||
|
mac_context.size(), enc_context.data(), enc_context.size());
|
||||||
|
if (result != OEMCrypto_SUCCESS) return result;
|
||||||
|
return pair.fcn->LoadLicense_V18(session, message, message_length,
|
||||||
|
core_message_length, signature,
|
||||||
|
signature_length);
|
||||||
}
|
}
|
||||||
return pair.fcn->LoadLicense(pair.session, message, message_length,
|
return pair.fcn->LoadLicense(pair.session, context, context_length,
|
||||||
core_message_length, signature,
|
derivation_key, derivation_key_length, message,
|
||||||
|
message_length, core_message_length, signature,
|
||||||
signature_length);
|
signature_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2144,7 +2199,7 @@ extern "C" OEMCryptoResult OEMCrypto_LoadRenewal(OEMCrypto_SESSION session,
|
|||||||
if (!gAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
if (!gAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
LevelSession pair = gAdapter->GetSession(session);
|
LevelSession pair = gAdapter->GetSession(session);
|
||||||
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
if (pair.fcn->LoadLicense == nullptr) {
|
if (pair.fcn->LoadRenewal == nullptr) {
|
||||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
return pair.fcn->LoadRenewal(pair.session, message, message_length,
|
return pair.fcn->LoadRenewal(pair.session, message, message_length,
|
||||||
@@ -2334,15 +2389,66 @@ extern "C" OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_LoadProvisioning(
|
extern "C" OEMCryptoResult OEMCrypto_LoadProvisioning(
|
||||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
OEMCrypto_SESSION session, const uint8_t* request, size_t request_length,
|
||||||
size_t core_message_length, const uint8_t* signature,
|
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||||
size_t signature_length, uint8_t* wrapped_private_key,
|
const uint8_t* signature, size_t signature_length,
|
||||||
size_t* wrapped_private_key_length) {
|
uint8_t* wrapped_private_key, size_t* wrapped_private_key_length) {
|
||||||
if (!gAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
if (!gAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
LevelSession pair = gAdapter->GetSession(session);
|
LevelSession pair = gAdapter->GetSession(session);
|
||||||
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
if (pair.fcn->LoadProvisioning != nullptr) {
|
if (pair.fcn->LoadProvisioning != nullptr) {
|
||||||
return pair.fcn->LoadProvisioning(
|
return pair.fcn->LoadProvisioning(
|
||||||
|
pair.session, request, request_length, message, message_length,
|
||||||
|
core_message_length, signature, signature_length, wrapped_private_key,
|
||||||
|
wrapped_private_key_length);
|
||||||
|
}
|
||||||
|
if (pair.fcn->LoadProvisioning_V18 != nullptr &&
|
||||||
|
pair.fcn->GenerateDerivedKeys_V18 != nullptr) {
|
||||||
|
const std::vector<uint8_t> mac_context =
|
||||||
|
MakeContext("AUTHENTICATION", request, request_length, 0x200);
|
||||||
|
const std::vector<uint8_t> enc_context =
|
||||||
|
MakeContext("ENCRYPTION", request, request_length, 0x80);
|
||||||
|
const OEMCryptoResult result = pair.fcn->GenerateDerivedKeys_V18(
|
||||||
|
pair.session, mac_context.data(), mac_context.size(),
|
||||||
|
enc_context.data(), enc_context.size());
|
||||||
|
if (result != OEMCrypto_SUCCESS) return result;
|
||||||
|
|
||||||
|
return pair.fcn->LoadProvisioning_V18(
|
||||||
|
pair.session, message, message_length, core_message_length, signature,
|
||||||
|
signature_length, wrapped_private_key, wrapped_private_key_length);
|
||||||
|
}
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" OEMCryptoResult OEMCrypto_LoadProvisioningCast(
|
||||||
|
OEMCrypto_SESSION session, const uint8_t* derivation_key,
|
||||||
|
size_t derivation_key_length, const uint8_t* provision_request,
|
||||||
|
size_t provision_request_length, const uint8_t* message,
|
||||||
|
size_t message_length, size_t core_message_length, const uint8_t* signature,
|
||||||
|
size_t signature_length, uint8_t* wrapped_private_key,
|
||||||
|
size_t* wrapped_private_key_length) {
|
||||||
|
if (!gAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
LevelSession pair = gAdapter->GetSession(session);
|
||||||
|
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
|
if (pair.fcn->LoadProvisioningCast != nullptr) {
|
||||||
|
return pair.fcn->LoadProvisioningCast(
|
||||||
|
pair.session, derivation_key, derivation_key_length, provision_request,
|
||||||
|
provision_request_length, message, message_length, core_message_length,
|
||||||
|
signature, signature_length, wrapped_private_key,
|
||||||
|
wrapped_private_key_length);
|
||||||
|
}
|
||||||
|
if (pair.fcn->LoadProvisioning_V18 != nullptr &&
|
||||||
|
pair.fcn->DeriveKeysFromSessionKey_V18 != nullptr) {
|
||||||
|
const std::vector<uint8_t> mac_context = MakeContext(
|
||||||
|
"AUTHENTICATION", provision_request, provision_request_length, 0x200);
|
||||||
|
const std::vector<uint8_t> enc_context = MakeContext(
|
||||||
|
"ENCRYPTION", provision_request, provision_request_length, 0x80);
|
||||||
|
const OEMCryptoResult result = pair.fcn->DeriveKeysFromSessionKey_V18(
|
||||||
|
pair.session, derivation_key, derivation_key_length, mac_context.data(),
|
||||||
|
mac_context.size(), enc_context.data(), enc_context.size());
|
||||||
|
if (result != OEMCrypto_SUCCESS) return result;
|
||||||
|
|
||||||
|
return pair.fcn->LoadProvisioning_V18(
|
||||||
pair.session, message, message_length, core_message_length, signature,
|
pair.session, message, message_length, core_message_length, signature,
|
||||||
signature_length, wrapped_private_key, wrapped_private_key_length);
|
signature_length, wrapped_private_key, wrapped_private_key_length);
|
||||||
}
|
}
|
||||||
@@ -2393,7 +2499,7 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateRSASignature(
|
|||||||
padding_scheme);
|
padding_scheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(
|
extern "C" OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey_V18(
|
||||||
OEMCrypto_SESSION session, const uint8_t* enc_session_key,
|
OEMCrypto_SESSION session, const uint8_t* enc_session_key,
|
||||||
size_t enc_session_key_length, const uint8_t* mac_key_context,
|
size_t enc_session_key_length, const uint8_t* mac_key_context,
|
||||||
size_t mac_key_context_length, const uint8_t* enc_key_context,
|
size_t mac_key_context_length, const uint8_t* enc_key_context,
|
||||||
@@ -2401,9 +2507,9 @@ extern "C" OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(
|
|||||||
if (!gAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
if (!gAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
LevelSession pair = gAdapter->GetSession(session);
|
LevelSession pair = gAdapter->GetSession(session);
|
||||||
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
if (pair.fcn->DeriveKeysFromSessionKey == nullptr)
|
if (pair.fcn->DeriveKeysFromSessionKey_V18 == nullptr)
|
||||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
return pair.fcn->DeriveKeysFromSessionKey(
|
return pair.fcn->DeriveKeysFromSessionKey_V18(
|
||||||
pair.session, enc_session_key, enc_session_key_length, mac_key_context,
|
pair.session, enc_session_key, enc_session_key_length, mac_key_context,
|
||||||
mac_key_context_length, enc_key_context, enc_key_context_length);
|
mac_key_context_length, enc_key_context, enc_key_context_length);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -275,18 +275,14 @@ bool FakeProvisioningServer::MakeResponse(
|
|||||||
// Next, we derive the keys from the keybox device key. This is Provisioning
|
// Next, we derive the keys from the keybox device key. This is Provisioning
|
||||||
// 2.0 specific.
|
// 2.0 specific.
|
||||||
// TODO(b/141438127): Add support for provisioing 3.0.
|
// TODO(b/141438127): Add support for provisioing 3.0.
|
||||||
std::string mac_context;
|
|
||||||
GenerateMacContext(serialized_message, &mac_context);
|
|
||||||
std::vector<uint8_t> mac_context_v(mac_context.begin(), mac_context.end());
|
|
||||||
std::string enc_context;
|
|
||||||
GenerateEncryptContext(serialized_message, &enc_context);
|
|
||||||
std::vector<uint8_t> enc_context_v(enc_context.begin(), enc_context.end());
|
|
||||||
wvoec::KeyDeriver key_deriver;
|
wvoec::KeyDeriver key_deriver;
|
||||||
|
std::vector<uint8_t> serialized_message_v(serialized_message.begin(),
|
||||||
|
serialized_message.end());
|
||||||
// Not only is this Prov 2.0 specific, it assumes the device is using the
|
// Not only is this Prov 2.0 specific, it assumes the device is using the
|
||||||
// standard test keybox.
|
// standard test keybox.
|
||||||
key_deriver.DeriveKeys(wvoec::kTestKeybox.device_key_,
|
key_deriver.DeriveKeys(wvoec::kTestKeybox.device_key_,
|
||||||
sizeof(wvoec::kTestKeybox.device_key_), mac_context_v,
|
sizeof(wvoec::kTestKeybox.device_key_),
|
||||||
enc_context_v);
|
serialized_message_v);
|
||||||
|
|
||||||
// Create a structure to hold the RSA private key. This is used by the key
|
// Create a structure to hold the RSA private key. This is used by the key
|
||||||
// deriver to encrypt the key.
|
// deriver to encrypt the key.
|
||||||
|
|||||||
@@ -605,7 +605,7 @@ typedef enum OEMCrypto_SignatureHashAlgorithm {
|
|||||||
#define OEMCrypto_RewrapDeviceRSAKey _oecc18
|
#define OEMCrypto_RewrapDeviceRSAKey _oecc18
|
||||||
#define OEMCrypto_LoadDeviceRSAKey _oecc19
|
#define OEMCrypto_LoadDeviceRSAKey _oecc19
|
||||||
#define OEMCrypto_GenerateRSASignature_V8 _oecc20
|
#define OEMCrypto_GenerateRSASignature_V8 _oecc20
|
||||||
#define OEMCrypto_DeriveKeysFromSessionKey _oecc21
|
#define OEMCrypto_DeriveKeysFromSessionKey_V18 _oecc21
|
||||||
#define OEMCrypto_APIVersion _oecc22
|
#define OEMCrypto_APIVersion _oecc22
|
||||||
#define OEMCrypto_SecurityLevel_V16 _oecc23
|
#define OEMCrypto_SecurityLevel_V16 _oecc23
|
||||||
#define OEMCrypto_Generic_Encrypt_V17 _oecc24
|
#define OEMCrypto_Generic_Encrypt_V17 _oecc24
|
||||||
@@ -669,13 +669,13 @@ typedef enum OEMCrypto_SignatureHashAlgorithm {
|
|||||||
#define OEMCrypto_LoadEntitledContentKeys_V16 _oecc92
|
#define OEMCrypto_LoadEntitledContentKeys_V16 _oecc92
|
||||||
#define OEMCrypto_CopyBuffer _oecc93
|
#define OEMCrypto_CopyBuffer _oecc93
|
||||||
#define OEMCrypto_MaximumUsageTableHeaderSize _oecc94
|
#define OEMCrypto_MaximumUsageTableHeaderSize _oecc94
|
||||||
#define OEMCrypto_GenerateDerivedKeys _oecc95
|
#define OEMCrypto_GenerateDerivedKeys_V18 _oecc95
|
||||||
#define OEMCrypto_PrepAndSignLicenseRequest _oecc96
|
#define OEMCrypto_PrepAndSignLicenseRequest _oecc96
|
||||||
#define OEMCrypto_PrepAndSignRenewalRequest _oecc97
|
#define OEMCrypto_PrepAndSignRenewalRequest _oecc97
|
||||||
#define OEMCrypto_PrepAndSignProvisioningRequest _oecc98
|
#define OEMCrypto_PrepAndSignProvisioningRequest _oecc98
|
||||||
#define OEMCrypto_LoadLicense _oecc99
|
#define OEMCrypto_LoadLicense_V18 _oecc99
|
||||||
#define OEMCrypto_LoadRenewal _oecc101
|
#define OEMCrypto_LoadRenewal _oecc101
|
||||||
#define OEMCrypto_LoadProvisioning _oecc102
|
#define OEMCrypto_LoadProvisioning_V18 _oecc102
|
||||||
#define OEMCrypto_LoadOEMPrivateKey _oecc103
|
#define OEMCrypto_LoadOEMPrivateKey _oecc103
|
||||||
#define OEMCrypto_GetOEMPublicCertificate _oecc104
|
#define OEMCrypto_GetOEMPublicCertificate _oecc104
|
||||||
#define OEMCrypto_DecryptCENC_V17 _oecc105
|
#define OEMCrypto_DecryptCENC_V17 _oecc105
|
||||||
@@ -716,6 +716,9 @@ typedef enum OEMCrypto_SignatureHashAlgorithm {
|
|||||||
#define OEMCrypto_GetDeviceSignedCsrPayload _oecc141
|
#define OEMCrypto_GetDeviceSignedCsrPayload _oecc141
|
||||||
#define OEMCrypto_FactoryInstallBCCSignature _oecc142
|
#define OEMCrypto_FactoryInstallBCCSignature _oecc142
|
||||||
#define OEMCrypto_SetDecryptHash _oecc143
|
#define OEMCrypto_SetDecryptHash _oecc143
|
||||||
|
#define OEMCrypto_LoadLicense _oecc144
|
||||||
|
#define OEMCrypto_LoadProvisioning _oecc145
|
||||||
|
#define OEMCrypto_LoadProvisioningCast _oecc146
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
/// @addtogroup initcontrol
|
/// @addtogroup initcontrol
|
||||||
@@ -953,159 +956,6 @@ OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session);
|
|||||||
*/
|
*/
|
||||||
OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session);
|
OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session);
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates three secondary keys, mac_key[server], mac_key[client], and
|
|
||||||
* encrypt_key, for handling signing and content key decryption under the
|
|
||||||
* license server protocol for CENC.
|
|
||||||
*
|
|
||||||
* Refer to the Key Derivation section above for more details. This function
|
|
||||||
* computes the AES-128-CMAC of the enc_key_context and stores it in secure
|
|
||||||
* memory as the encrypt_key. It then computes four cycles of AES-128-CMAC of
|
|
||||||
* the mac_key_context and stores it in the mac_keys -- the first two cycles
|
|
||||||
* generate the mac_key[server] and the second two cycles generate the
|
|
||||||
* mac_key[client]. These two keys will be stored until the next call to
|
|
||||||
* OEMCrypto_LoadLicense(). The device key from the keybox is used as the key
|
|
||||||
* for the AES-128-CMAC.
|
|
||||||
*
|
|
||||||
* @param[in] session: handle for the session to be used.
|
|
||||||
* @param[in] mac_key_context: pointer to memory containing context data for
|
|
||||||
* computing the HMAC generation key.
|
|
||||||
* @param[in] mac_key_context_length: length of the HMAC key context data, in
|
|
||||||
* bytes.
|
|
||||||
* @param[in] enc_key_context: pointer to memory containing context data for
|
|
||||||
* computing the encryption key.
|
|
||||||
* @param[in] enc_key_context_length: length of the encryption key context data,
|
|
||||||
* in bytes.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* mac_key[server]: the 256 bit mac key is generated and stored in secure
|
|
||||||
* memory.
|
|
||||||
* mac_key[client]: the 256 bit mac key is generated and stored in secure
|
|
||||||
* memory.
|
|
||||||
* enc_key: the 128 bit encryption key is generated and stored in secure
|
|
||||||
* memory.
|
|
||||||
*
|
|
||||||
* @retval OEMCrypto_SUCCESS success
|
|
||||||
* @retval OEMCrypto_ERROR_NO_DEVICE_KEY
|
|
||||||
* @retval OEMCrypto_ERROR_INVALID_SESSION
|
|
||||||
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
|
||||||
* @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
|
|
||||||
* @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
|
|
||||||
* @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
|
|
||||||
* @retval OEMCrypto_ERROR_SESSION_LOST_STATE
|
|
||||||
* @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
|
|
||||||
*
|
|
||||||
* @buffer_size
|
|
||||||
* OEMCrypto shall support mac_key_context and enc_key_context sizes as
|
|
||||||
* described in the section OEMCrypto_ResourceRatingTier() for messages. The
|
|
||||||
* key derivation context is about 25 bytes prepended to the request message.
|
|
||||||
* OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffers are
|
|
||||||
* too large.
|
|
||||||
*
|
|
||||||
* @threading
|
|
||||||
* This is a "Session Function" and may be called simultaneously with session
|
|
||||||
* functions for other sessions but not simultaneously with other functions
|
|
||||||
* for this session. It will not be called simultaneously with initialization
|
|
||||||
* or usage table functions. It is as if the CDM holds a write lock for this
|
|
||||||
* session, and a read lock on the OEMCrypto system.
|
|
||||||
*
|
|
||||||
* @version
|
|
||||||
* This method changed in API version 12.
|
|
||||||
*/
|
|
||||||
OEMCryptoResult OEMCrypto_GenerateDerivedKeys(
|
|
||||||
OEMCrypto_SESSION session, const OEMCrypto_SharedMemory* mac_key_context,
|
|
||||||
size_t mac_key_context_length,
|
|
||||||
const OEMCrypto_SharedMemory* enc_key_context,
|
|
||||||
size_t enc_key_context_length);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates three secondary keys, mac_key[server], mac_key[client] and
|
|
||||||
* encrypt_key, for handling signing and content key decryption under the
|
|
||||||
* license server protocol for CENC.
|
|
||||||
*
|
|
||||||
* This function is similar to OEMCrypto_GenerateDerivedKeys(), except that it
|
|
||||||
* uses a session key to generate the secondary keys instead of the Widevine
|
|
||||||
* Keybox device key. These three keys will be stored in secure memory until
|
|
||||||
* the next call to LoadLicense or LoadProvisioning.
|
|
||||||
*
|
|
||||||
* If the session's private key is an RSA key, then the session key is passed
|
|
||||||
* in encrypted by the device RSA public key as the derivation_key, and must
|
|
||||||
* be decrypted with the RSA private key before use.
|
|
||||||
*
|
|
||||||
* If the sesion's private key is an ECC key, then the session key is the
|
|
||||||
* SHA256 of the shared secret key calculated by ECDH between the device's
|
|
||||||
* ECC private key and the derivation_key. See the document "OEMCrypto
|
|
||||||
* Elliptic Curve Support" for details.
|
|
||||||
*
|
|
||||||
* Once the enc_key and mac_keys have been generated, all calls to
|
|
||||||
* OEMCrypto_LoadLicense() proceed in the same manner for license requests using
|
|
||||||
* RSA or using a Widevine keybox token.
|
|
||||||
*
|
|
||||||
* This function is also used to derive keys before processing a Cast
|
|
||||||
* Certificate provisioning response in OEMCrypto_LoadProvisioning().
|
|
||||||
* See [Cast Receiver](../../cast) for more details.
|
|
||||||
*
|
|
||||||
* @verification
|
|
||||||
* If the RSA key's allowed_schemes is not kSign_RSASSA_PSS, then no keys are
|
|
||||||
* derived and the error OEMCrypto_ERROR_INVALID_KEY is returned. An RSA
|
|
||||||
* key cannot be used for both deriving session keys and also for PKCS1
|
|
||||||
* signatures.
|
|
||||||
*
|
|
||||||
* @param[in] session: handle for the session to be used.
|
|
||||||
* @param[in] derivation_key: session key, encrypted with the public RSA key
|
|
||||||
* (from the DRM certifcate) using RSA-OAEP.
|
|
||||||
* @param[in] derivation_key_length: length of derivation_key, in bytes.
|
|
||||||
* @param[in] mac_key_context: pointer to memory containing context data for
|
|
||||||
* computing the HMAC generation key.
|
|
||||||
* @param[in] mac_key_context_length: length of the HMAC key context data, in
|
|
||||||
* bytes.
|
|
||||||
* @param[in] enc_key_context: pointer to memory containing context data for
|
|
||||||
* computing the encryption key.
|
|
||||||
* @param[in] enc_key_context_length: length of the encryption key context data,
|
|
||||||
* in bytes.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* mac_key[server]: the 256 bit mac key is generated and stored in secure
|
|
||||||
* memory.
|
|
||||||
* mac_key[client]: the 256 bit mac key is generated and stored in secure
|
|
||||||
* memory.
|
|
||||||
* enc_key: the 128 bit encryption key is generated and stored in secure
|
|
||||||
* memory.
|
|
||||||
*
|
|
||||||
* @retval OEMCrypto_SUCCESS success
|
|
||||||
* @retval OEMCrypto_ERROR_DEVICE_NOT_RSA_PROVISIONED
|
|
||||||
* @retval OEMCrypto_ERROR_INVALID_SESSION
|
|
||||||
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
|
||||||
* @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
|
|
||||||
* @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
|
|
||||||
* @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
|
|
||||||
* @retval OEMCrypto_ERROR_SESSION_LOST_STATE
|
|
||||||
* @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
|
|
||||||
*
|
|
||||||
* @buffer_size
|
|
||||||
* OEMCrypto shall support mac_key_context and enc_key_context sizes as
|
|
||||||
* described in the section OEMCrypto_ResourceRatingTier() for messages. The
|
|
||||||
* key derivation context is about 25 bytes prepended to the request message.
|
|
||||||
* OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffers are
|
|
||||||
* too large.
|
|
||||||
*
|
|
||||||
* @threading
|
|
||||||
* This is a "Session Function" and may be called simultaneously with session
|
|
||||||
* functions for other sessions but not simultaneously with other functions
|
|
||||||
* for this session. It will not be called simultaneously with initialization
|
|
||||||
* or usage table functions. It is as if the CDM holds a write lock for this
|
|
||||||
* session, and a read lock on the OEMCrypto system.
|
|
||||||
*
|
|
||||||
* @version
|
|
||||||
* This method changed in API version 16.
|
|
||||||
*/
|
|
||||||
OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(
|
|
||||||
OEMCrypto_SESSION session, const uint8_t* derivation_key,
|
|
||||||
size_t derivation_key_length, const OEMCrypto_SharedMemory* mac_key_context,
|
|
||||||
size_t mac_key_context_length,
|
|
||||||
const OEMCrypto_SharedMemory* enc_key_context,
|
|
||||||
size_t enc_key_context_length);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a 32-bit nonce to detect possible replay attack on the key
|
* Generates a 32-bit nonce to detect possible replay attack on the key
|
||||||
* control block. The nonce is stored in secure memory and will be used in
|
* control block. The nonce is stored in secure memory and will be used in
|
||||||
@@ -1308,7 +1158,11 @@ OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
|
|||||||
/**
|
/**
|
||||||
* Install a set of keys for performing decryption in the current session.
|
* Install a set of keys for performing decryption in the current session.
|
||||||
*
|
*
|
||||||
* First, OEMCrypto shall verify the signature of the message using
|
* First, OEMCrypto should generate three secondary keys, mac_key[server],
|
||||||
|
* mac_key[client], and encryption_key, for handling signing and content key
|
||||||
|
* derivation under the license server protocol for CENC.
|
||||||
|
*
|
||||||
|
* Then OEMCrypto shall verify the signature of the message using
|
||||||
* HMAC-SHA256 with the derived mac_key[server]. The signature verification
|
* HMAC-SHA256 with the derived mac_key[server]. The signature verification
|
||||||
* shall use a constant-time algorithm (a signature mismatch will always take
|
* shall use a constant-time algorithm (a signature mismatch will always take
|
||||||
* the same time as a successful comparison). The signature is over the
|
* the same time as a successful comparison). The signature is over the
|
||||||
@@ -1317,9 +1171,6 @@ OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
|
|||||||
* OEMCrypto_ERROR_SIGNATURE_FAILURE. Otherwise, add the keys to the session
|
* OEMCrypto_ERROR_SIGNATURE_FAILURE. Otherwise, add the keys to the session
|
||||||
* context.
|
* context.
|
||||||
*
|
*
|
||||||
* NOTE: The calling software must have previously established the mac_keys
|
|
||||||
* and encrypt_key with a call to OEMCrypto_DeriveKeysFromSessionKey().
|
|
||||||
*
|
|
||||||
* Refer to the Verification of Messages from a Server section above for more
|
* Refer to the Verification of Messages from a Server section above for more
|
||||||
* details.
|
* details.
|
||||||
*
|
*
|
||||||
@@ -1517,6 +1368,10 @@ OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
|
|||||||
* OEMCrypto_ERROR_INSUFFICIENT_HDCP at that time.
|
* OEMCrypto_ERROR_INSUFFICIENT_HDCP at that time.
|
||||||
*
|
*
|
||||||
* @param[in] session: crypto session identifier.
|
* @param[in] session: crypto session identifier.
|
||||||
|
* @param[in] context: pointer to memory containing context data.
|
||||||
|
* @param[in] context_length: length of the context, in bytes.
|
||||||
|
* @param[in] derivation_key: pointer to memory containing derivation key.
|
||||||
|
* @param[in] derivation_key_length: length of the derivation_key, in bytes.
|
||||||
* @param[in] message: pointer to memory containing data.
|
* @param[in] message: pointer to memory containing data.
|
||||||
* @param[in] message_length: length of the message, in bytes.
|
* @param[in] message_length: length of the message, in bytes.
|
||||||
* @param[in] core_message_length: length of the core submessage, in bytes.
|
* @param[in] core_message_length: length of the core submessage, in bytes.
|
||||||
@@ -1537,6 +1392,8 @@ OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
|
|||||||
* @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
|
* @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
|
||||||
* @retval OEMCrypto_ERROR_LICENSE_RELOAD
|
* @retval OEMCrypto_ERROR_LICENSE_RELOAD
|
||||||
* @retval OEMCrypto_ERROR_KEY_EXPIRED
|
* @retval OEMCrypto_ERROR_KEY_EXPIRED
|
||||||
|
* @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
|
||||||
|
* @retval OEMCrypto_ERROR_DEVICE_NOT_RSA_PROVISIONED
|
||||||
*
|
*
|
||||||
* @buffer_size
|
* @buffer_size
|
||||||
* OEMCrypto shall support message sizes as described in the section
|
* OEMCrypto shall support message sizes as described in the section
|
||||||
@@ -1554,12 +1411,11 @@ OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
|
|||||||
* @version
|
* @version
|
||||||
* This method changed in API version 16.
|
* This method changed in API version 16.
|
||||||
*/
|
*/
|
||||||
OEMCryptoResult OEMCrypto_LoadLicense(OEMCrypto_SESSION session,
|
OEMCryptoResult OEMCrypto_LoadLicense(
|
||||||
const uint8_t* message,
|
OEMCrypto_SESSION session, const uint8_t* context, size_t context_length,
|
||||||
size_t message_length,
|
const uint8_t* derivation_key, size_t derivation_key_length,
|
||||||
size_t core_message_length,
|
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||||
const uint8_t* signature,
|
const uint8_t* signature, size_t signature_length);
|
||||||
size_t signature_length);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the clock values and resets the renewal timer for the current
|
* Updates the clock values and resets the renewal timer for the current
|
||||||
@@ -3783,9 +3639,7 @@ uint32_t OEMCrypto_GetAnalogOutputFlags(void);
|
|||||||
* The message size limit applies to all functions that sign or verify a
|
* The message size limit applies to all functions that sign or verify a
|
||||||
* message: OEMCrypto_PrepAndSignLicenseRequest(),
|
* message: OEMCrypto_PrepAndSignLicenseRequest(),
|
||||||
* OEMCrypto_PrepAndSignRenewalRequest(),
|
* OEMCrypto_PrepAndSignRenewalRequest(),
|
||||||
* OEMCrypto_PrepAndSignProvisioningRequest(), and OEMCrypto_LoadLicense(). A
|
* OEMCrypto_PrepAndSignProvisioningRequest(), and OEMCrypto_LoadLicense().
|
||||||
* request message is also used as the context buffer in
|
|
||||||
* OEMCrypto_DeriveKeysFromSessionKey() and OEMCrypto_GenerateDerivedKeys().
|
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
@@ -3918,24 +3772,19 @@ OEMCryptoResult OEMCrypto_GetSignatureHashAlgorithm(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Load and parse a provisioning response, and then rewrap the private key
|
* Load and parse a provisioning response, and then rewrap the private key
|
||||||
* for storage on the filesystem. We recommend that the OEM use an encryption
|
* for storage on the filesystem. We recommend that the OEM use a strong
|
||||||
* key and signing key generated using an algorithm at least as strong as
|
* encryption key and signing key algorithm.
|
||||||
* that in GenerateDerivedKeys.
|
|
||||||
*
|
*
|
||||||
* First, OEMCrypto shall verify the signature of the message using the correct
|
* First, OEMCrypto shall verify the signature of the message using the correct
|
||||||
* algorithm depending on if the device supports Provisioning 2.0, 3.0 or 4.0.
|
* algorithm depending on if the device supports Provisioning 2.0, 3.0 or 4.0.
|
||||||
*
|
*
|
||||||
* For Provisioning 2.0, OEMCrypto shall verify the signature of the message
|
* For Provisioning 2.0, OEMCrypto shall use the provisioning request to derive
|
||||||
* using HMAC-SHA256 with the derived mac_key[server]. The signature
|
* mac_key[server] and verify the signature of the message using HMAC-SHA256.
|
||||||
* verification shall use a constant-time algorithm (a signature mismatch will
|
* The signature verification shall use a constant-time algorithm (a signature
|
||||||
* always take the same time as a successful comparison). The signature is over
|
* mismatch will always take the same time as a successful comparison). The
|
||||||
* the entire message buffer starting at message with length message_length. If
|
* signature is over the entire message buffer starting at message with length
|
||||||
* the signature verification fails, ignore all other arguments and return
|
* message_length. If the signature verification fails, ignore all other
|
||||||
* OEMCrypto_ERROR_SIGNATURE_FAILURE.
|
* arguments and return OEMCrypto_ERROR_SIGNATURE_FAILURE.
|
||||||
*
|
|
||||||
* NOTE: The calling software must have previously established the mac_keys
|
|
||||||
* and encrypt_key with a call to OEMCrypto_DeriveKeysFromSessionKey() or
|
|
||||||
* OEMCrypto_GenerateDerivedKeys().
|
|
||||||
*
|
*
|
||||||
* For Provisioning 3.0 and 4.0, the signature is not verified.
|
* For Provisioning 3.0 and 4.0, the signature is not verified.
|
||||||
*
|
*
|
||||||
@@ -3973,8 +3822,7 @@ OEMCryptoResult OEMCrypto_GetSignatureHashAlgorithm(
|
|||||||
* 2. Verify that (in) wrapped_private_key_length is large enough to hold
|
* 2. Verify that (in) wrapped_private_key_length is large enough to hold
|
||||||
* the rewrapped key, returning OEMCrypto_ERROR_SHORT_BUFFER otherwise.
|
* the rewrapped key, returning OEMCrypto_ERROR_SHORT_BUFFER otherwise.
|
||||||
* 3. Verify the message signature, using the derived signing key
|
* 3. Verify the message signature, using the derived signing key
|
||||||
* (mac_key[server]) from a previous call to
|
* (mac_key[server]).
|
||||||
* OEMCrypto_GenerateDerivedKeys() or OEMCrypto_DeriveKeysFromSessionKey().
|
|
||||||
* 4. The function ODK_ParseProvisioning is called to parse the message.
|
* 4. The function ODK_ParseProvisioning is called to parse the message.
|
||||||
* 5. Decrypt enc_private_key in the buffer private_key using the session's
|
* 5. Decrypt enc_private_key in the buffer private_key using the session's
|
||||||
* derived encryption key (enc_key). Use enc_private_key_iv as the initial
|
* derived encryption key (enc_key). Use enc_private_key_iv as the initial
|
||||||
@@ -4011,6 +3859,8 @@ OEMCryptoResult OEMCrypto_GetSignatureHashAlgorithm(
|
|||||||
* and the size of the wrapped key to wrapped_private_key_length.
|
* and the size of the wrapped key to wrapped_private_key_length.
|
||||||
*
|
*
|
||||||
* @param[in] session: crypto session identifier.
|
* @param[in] session: crypto session identifier.
|
||||||
|
* @param[in] provision_request: the initial provisioning request.
|
||||||
|
* @param[in] provision_request_length: length of provision_request, in bytes.
|
||||||
* @param[in] message: pointer to memory containing data.
|
* @param[in] message: pointer to memory containing data.
|
||||||
* @param[in] message_length: length of the message, in bytes.
|
* @param[in] message_length: length of the message, in bytes.
|
||||||
* @param[in] core_message_length: length of the core submessage, in bytes.
|
* @param[in] core_message_length: length of the core submessage, in bytes.
|
||||||
@@ -4052,15 +3902,79 @@ OEMCryptoResult OEMCrypto_GetSignatureHashAlgorithm(
|
|||||||
* This method changed in API version 16.
|
* This method changed in API version 16.
|
||||||
*/
|
*/
|
||||||
OEMCryptoResult OEMCrypto_LoadProvisioning(
|
OEMCryptoResult OEMCrypto_LoadProvisioning(
|
||||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
OEMCrypto_SESSION session, const uint8_t* provision_request,
|
||||||
size_t core_message_length, const uint8_t* signature,
|
size_t provision_request_length, const uint8_t* message,
|
||||||
|
size_t message_length, size_t core_message_length, const uint8_t* signature,
|
||||||
|
size_t signature_length, uint8_t* wrapped_private_key,
|
||||||
|
size_t* wrapped_private_key_length);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load and parse a provisioning response, and then rewrap the private key. We
|
||||||
|
* recommend that the OEM use a strong encryption key and signing key algorithm.
|
||||||
|
*
|
||||||
|
* This is the same as OEMCrypto_LoadProvisioning except it is for CAST devices.
|
||||||
|
* This should return OEMCrypto_ERROR_NOT_IMPLEMENTED for non-CAST devices.
|
||||||
|
*
|
||||||
|
* @param[in] session: crypto session identifier.
|
||||||
|
* @param[in] derivation_key: session key, encrypted with the public RSA key
|
||||||
|
* (from the DRM certifcate) using RSA-OAEP.
|
||||||
|
* @param[in] derivation_key_length: length of derivation_key, in bytes.
|
||||||
|
* @param[in] provision_request: the initial provisioning request.
|
||||||
|
* @param[in] provision_request_length: length of provision_request, in bytes.
|
||||||
|
* @param[in] message: pointer to memory containing data.
|
||||||
|
* @param[in] message_length: length of the message, in bytes.
|
||||||
|
* @param[in] core_message_length: length of the core submessage, in bytes.
|
||||||
|
* @param[in] signature: pointer to memory containing the signature.
|
||||||
|
* @param[in] signature_length: length of the signature, in bytes.
|
||||||
|
* @param[out] wrapped_private_key: pointer to buffer in which encrypted RSA or
|
||||||
|
* ECC private key should be stored. May be null on the first call in order
|
||||||
|
* to find required buffer size.
|
||||||
|
* @param[in,out] wrapped_private_key_length: (in) length of the encrypted
|
||||||
|
* private key, in bytes. (out) actual length of the encrypted private key
|
||||||
|
*
|
||||||
|
* @retval OEMCrypto_SUCCESS success
|
||||||
|
* @retval OEMCrypto_ERROR_NO_DEVICE_KEY
|
||||||
|
* @retval OEMCrypto_ERROR_INVALID_SESSION
|
||||||
|
* @retval OEMCrypto_ERROR_INVALID_KEY
|
||||||
|
* @retval OEMCrypto_ERROR_SIGNATURE_FAILURE
|
||||||
|
* @retval OEMCrypto_ERROR_INVALID_NONCE
|
||||||
|
* @retval OEMCrypto_ERROR_SHORT_BUFFER
|
||||||
|
* @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
|
||||||
|
* @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||||
|
* @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
|
||||||
|
* @retval OEMCrypto_ERROR_SESSION_LOST_STATE
|
||||||
|
* @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
|
||||||
|
* @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
|
||||||
|
*
|
||||||
|
* @buffer_size
|
||||||
|
* OEMCrypto shall support message sizes as described in the section
|
||||||
|
* OEMCrypto_ResourceRatingTier().
|
||||||
|
* OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
|
||||||
|
* larger than the supported size.
|
||||||
|
*
|
||||||
|
* @threading
|
||||||
|
* This is a "Session Function" and may be called simultaneously with session
|
||||||
|
* functions for other sessions but not simultaneously with other functions
|
||||||
|
* for this session. It will not be called simultaneously with initialization
|
||||||
|
* or usage table functions. It is as if the CDM holds a write lock for this
|
||||||
|
* session, and a read lock on the OEMCrypto system.
|
||||||
|
*
|
||||||
|
* @version
|
||||||
|
* This method was added in API version 19.
|
||||||
|
*/
|
||||||
|
OEMCryptoResult OEMCrypto_LoadProvisioningCast(
|
||||||
|
OEMCrypto_SESSION session, const uint8_t* derivation_key,
|
||||||
|
size_t derivation_key_length, const uint8_t* provision_request,
|
||||||
|
size_t provision_request_length, const uint8_t* message,
|
||||||
|
size_t message_length, size_t core_message_length, const uint8_t* signature,
|
||||||
size_t signature_length, uint8_t* wrapped_private_key,
|
size_t signature_length, uint8_t* wrapped_private_key,
|
||||||
size_t* wrapped_private_key_length);
|
size_t* wrapped_private_key_length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a wrapped RSA or ECC private key to secure memory for use by this
|
* Loads a wrapped RSA or ECC private key to secure memory for use by this
|
||||||
* session in future calls to OEMCrypto_PrepAndSignLicenseRequest() or
|
* session in future calls to OEMCrypto_PrepAndSignLicenseRequest() or
|
||||||
* OEMCrypto_DeriveKeysFromSessionKey(). The wrapped private key will be the
|
* OEMCrypto_LoadLicense(). The wrapped private key will be the
|
||||||
* one verified and wrapped by OEMCrypto_LoadProvisioning(). The private key
|
* one verified and wrapped by OEMCrypto_LoadProvisioning(). The private key
|
||||||
* should be stored in secure memory.
|
* should be stored in secure memory.
|
||||||
*
|
*
|
||||||
@@ -4068,7 +3982,7 @@ OEMCryptoResult OEMCrypto_LoadProvisioning(
|
|||||||
* value will be loaded and stored with the RSA key, and the key may be used
|
* value will be loaded and stored with the RSA key, and the key may be used
|
||||||
* with calls to OEMCrypto_GenerateRSASignature(). If there was not a bit field
|
* with calls to OEMCrypto_GenerateRSASignature(). If there was not a bit field
|
||||||
* wrapped with the RSA key, the key will be used for
|
* wrapped with the RSA key, the key will be used for
|
||||||
* OEMCrypto_PrepAndSignLicenseRequest() or OEMCrypto_DeriveKeysFromSessionKey()
|
* OEMCrypto_PrepAndSignLicenseRequest() or OEMCrypto_LoadLicense()
|
||||||
*
|
*
|
||||||
* @verification
|
* @verification
|
||||||
* The following checks should be performed. If any check fails, an error is
|
* The following checks should be performed. If any check fails, an error is
|
||||||
@@ -4228,8 +4142,7 @@ OEMCryptoResult OEMCrypto_GenerateRSASignature(
|
|||||||
* message with length message_length.
|
* message with length message_length.
|
||||||
*
|
*
|
||||||
* For a device that has a keybox, i.e. Provisioning 2.0, OEMCrypto will sign
|
* For a device that has a keybox, i.e. Provisioning 2.0, OEMCrypto will sign
|
||||||
* the request with the session's derived client mac key from the previous
|
* the request with the session's derived client mac key using the message.
|
||||||
* call to OEMCrypto_GenerateDerivedKeys().
|
|
||||||
*
|
*
|
||||||
* For Provisioning 3.0, i.e. a device that has a baked in OEM Certificate,
|
* For Provisioning 3.0, i.e. a device that has a baked in OEM Certificate,
|
||||||
* OEMCrypto will sign the request with the private key associated with the OEM
|
* OEMCrypto will sign the request with the private key associated with the OEM
|
||||||
@@ -5845,6 +5758,56 @@ OEMCryptoResult OEMCrypto_Generic_Verify_V17(
|
|||||||
size_t buffer_length, OEMCrypto_Algorithm algorithm,
|
size_t buffer_length, OEMCrypto_Algorithm algorithm,
|
||||||
const OEMCrypto_SharedMemory* signature, size_t signature_length);
|
const OEMCrypto_SharedMemory* signature, size_t signature_length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OEMCrypto_GenerateDerivedKeys_V18
|
||||||
|
* @deprecated
|
||||||
|
* Not required for the current version of OEMCrypto. Declared here to
|
||||||
|
* help with backward compatibility.
|
||||||
|
*/
|
||||||
|
OEMCryptoResult OEMCrypto_GenerateDerivedKeys_V18(
|
||||||
|
OEMCrypto_SESSION session, const OEMCrypto_SharedMemory* mac_key_context,
|
||||||
|
size_t mac_key_context_length,
|
||||||
|
const OEMCrypto_SharedMemory* enc_key_context,
|
||||||
|
size_t enc_key_context_length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OEMCrypto_DeriveKeysFromSessionKey_V18
|
||||||
|
* @deprecated
|
||||||
|
* Not required for the current version of OEMCrypto. Declared here to
|
||||||
|
* help with backward compatibility.
|
||||||
|
*/
|
||||||
|
OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey_V18(
|
||||||
|
OEMCrypto_SESSION session, const uint8_t* derivation_key,
|
||||||
|
size_t derivation_key_length, const OEMCrypto_SharedMemory* mac_key_context,
|
||||||
|
size_t mac_key_context_length,
|
||||||
|
const OEMCrypto_SharedMemory* enc_key_context,
|
||||||
|
size_t enc_key_context_length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OEMCrypto_LoadLicense_V18
|
||||||
|
* @deprecated
|
||||||
|
* Not required for the current version of OEMCrypto. Declared here to
|
||||||
|
* help with backward compatibility.
|
||||||
|
*/
|
||||||
|
OEMCryptoResult OEMCrypto_LoadLicense_V18(OEMCrypto_SESSION session,
|
||||||
|
const uint8_t* message,
|
||||||
|
size_t message_length,
|
||||||
|
size_t core_message_length,
|
||||||
|
const uint8_t* signature,
|
||||||
|
size_t signature_length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OEMCrypto_LoadProvisioning_V18
|
||||||
|
* @deprecated
|
||||||
|
* Not required for the current version of OEMCrypto. Declared here to
|
||||||
|
* help with backward compatibility.
|
||||||
|
*/
|
||||||
|
OEMCryptoResult OEMCrypto_LoadProvisioning_V18(
|
||||||
|
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||||
|
size_t core_message_length, const uint8_t* signature,
|
||||||
|
size_t signature_length, uint8_t* wrapped_private_key,
|
||||||
|
size_t* wrapped_private_key_length);
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,23 @@ using namespace std;
|
|||||||
|
|
||||||
namespace wvoec {
|
namespace wvoec {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::vector<uint8_t> CreateContext(const char* prefix,
|
||||||
|
const std::vector<uint8_t>& context,
|
||||||
|
uint32_t suffix) {
|
||||||
|
std::vector<uint8_t> ret;
|
||||||
|
// +1 to include the null-terminator
|
||||||
|
ret.insert(ret.end(), prefix, prefix + strlen(prefix) + 1);
|
||||||
|
ret.insert(ret.end(), context.begin(), context.end());
|
||||||
|
const uint32_t suffix_net = htonl(suffix);
|
||||||
|
auto* ptr = reinterpret_cast<const uint8_t*>(&suffix_net);
|
||||||
|
ret.insert(ret.end(), ptr, ptr + sizeof(suffix_net));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void Encryptor::set_enc_key(const std::vector<uint8_t>& enc_key) {
|
void Encryptor::set_enc_key(const std::vector<uint8_t>& enc_key) {
|
||||||
enc_key_ = enc_key;
|
enc_key_ = enc_key;
|
||||||
}
|
}
|
||||||
@@ -119,8 +136,21 @@ void KeyDeriver::DeriveKey(const uint8_t* key, size_t master_key_size,
|
|||||||
// this function, then there is something wrong with the test program and its
|
// this function, then there is something wrong with the test program and its
|
||||||
// dependency on BoringSSL.
|
// dependency on BoringSSL.
|
||||||
void KeyDeriver::DeriveKeys(const uint8_t* master_key, size_t master_key_size,
|
void KeyDeriver::DeriveKeys(const uint8_t* master_key, size_t master_key_size,
|
||||||
const vector<uint8_t>& mac_key_context,
|
const vector<uint8_t>& context) {
|
||||||
const vector<uint8_t>& enc_key_context) {
|
// TODO: Use ODK constants instead
|
||||||
|
DeriveKeys(master_key, master_key_size, context, "AUTHENTICATION",
|
||||||
|
"ENCRYPTION");
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyDeriver::DeriveKeys(const uint8_t* master_key, size_t master_key_size,
|
||||||
|
const vector<uint8_t>& context,
|
||||||
|
const char* mac_label, const char* enc_label) {
|
||||||
|
// TODO: Use ODK constants instead
|
||||||
|
const std::vector<uint8_t> mac_key_context =
|
||||||
|
CreateContext(mac_label, context, 0x200);
|
||||||
|
const std::vector<uint8_t> enc_key_context =
|
||||||
|
CreateContext(enc_label, context, 0x80);
|
||||||
|
|
||||||
// Generate derived key for mac key
|
// Generate derived key for mac key
|
||||||
std::vector<uint8_t> mac_key_part2;
|
std::vector<uint8_t> mac_key_part2;
|
||||||
DeriveKey(master_key, master_key_size, mac_key_context, 1, &mac_key_server_);
|
DeriveKey(master_key, master_key_size, mac_key_context, 1, &mac_key_server_);
|
||||||
|
|||||||
@@ -73,8 +73,10 @@ class KeyDeriver : public Encryptor {
|
|||||||
|
|
||||||
// Generate mac and enc keys give the master key.
|
// Generate mac and enc keys give the master key.
|
||||||
void DeriveKeys(const uint8_t* master_key, size_t master_key_size,
|
void DeriveKeys(const uint8_t* master_key, size_t master_key_size,
|
||||||
const std::vector<uint8_t>& mac_key_context,
|
const std::vector<uint8_t>& context);
|
||||||
const std::vector<uint8_t>& enc_key_context);
|
void DeriveKeys(const uint8_t* master_key, size_t master_key_size,
|
||||||
|
const std::vector<uint8_t>& context, const char* mac_label,
|
||||||
|
const char* enc_label);
|
||||||
// Sign the buffer with server's mac key.
|
// Sign the buffer with server's mac key.
|
||||||
void ServerSignBuffer(const uint8_t* data, size_t data_length,
|
void ServerSignBuffer(const uint8_t* data, size_t data_length,
|
||||||
std::vector<uint8_t>* signature) const;
|
std::vector<uint8_t>* signature) const;
|
||||||
|
|||||||
@@ -234,7 +234,8 @@ RoundTrip<CoreRequest, PrepAndSignRequest, CoreResponse, ResponseData>::
|
|||||||
// verified by the server. This simulates that.
|
// verified by the server. This simulates that.
|
||||||
size_t gen_signature_length = 0;
|
size_t gen_signature_length = 0;
|
||||||
size_t core_message_length = 0;
|
size_t core_message_length = 0;
|
||||||
constexpr size_t small_size = 42; // arbitrary.
|
const vector<uint8_t> context = session()->GetDefaultContext();
|
||||||
|
const size_t small_size = context.size(); // arbitrary.
|
||||||
if (RequestHasNonce()) {
|
if (RequestHasNonce()) {
|
||||||
session()->GenerateNonce();
|
session()->GenerateNonce();
|
||||||
}
|
}
|
||||||
@@ -252,7 +253,10 @@ RoundTrip<CoreRequest, PrepAndSignRequest, CoreResponse, ResponseData>::
|
|||||||
size_t message_size =
|
size_t message_size =
|
||||||
std::max(required_message_size_, core_message_length + small_size);
|
std::max(required_message_size_, core_message_length + small_size);
|
||||||
vector<uint8_t> data(message_size);
|
vector<uint8_t> data(message_size);
|
||||||
for (size_t i = 0; i < data.size(); i++) data[i] = i & 0xFF;
|
memcpy(&data[core_message_length], context.data(), context.size());
|
||||||
|
for (size_t i = context.size() + core_message_length; i < data.size(); i++) {
|
||||||
|
data[i] = i & 0xFF;
|
||||||
|
}
|
||||||
if (ShouldGenerateCorpus()) {
|
if (ShouldGenerateCorpus()) {
|
||||||
WriteRequestApiCorpus<CoreRequest>(gen_signature_length,
|
WriteRequestApiCorpus<CoreRequest>(gen_signature_length,
|
||||||
core_message_length, data);
|
core_message_length, data);
|
||||||
@@ -348,29 +352,37 @@ void ProvisioningRoundTrip::PrepareSession(
|
|||||||
const wvoec::WidevineKeybox& keybox) {
|
const wvoec::WidevineKeybox& keybox) {
|
||||||
ASSERT_NO_FATAL_FAILURE(session_->open());
|
ASSERT_NO_FATAL_FAILURE(session_->open());
|
||||||
if (global_features.provisioning_method == OEMCrypto_Keybox) {
|
if (global_features.provisioning_method == OEMCrypto_Keybox) {
|
||||||
session_->GenerateDerivedKeysFromKeybox(keybox);
|
keybox_ = &keybox;
|
||||||
encryptor_ = session_->key_deriver();
|
|
||||||
} else if (global_features.provisioning_method ==
|
} else if (global_features.provisioning_method ==
|
||||||
OEMCrypto_BootCertificateChain) {
|
OEMCrypto_BootCertificateChain) {
|
||||||
// TODO(chelu): change this to CSR provisioning.
|
// TODO(chelu): change this to CSR provisioning.
|
||||||
session_->LoadOEMCert(true);
|
session_->LoadOEMCert(true);
|
||||||
session_->GenerateRsaSessionKey(&message_key_, &encrypted_message_key_);
|
session_->GenerateRsaSessionKey();
|
||||||
encryptor_.set_enc_key(message_key_);
|
encryptor_.set_enc_key(session_->session_key());
|
||||||
} else {
|
} else {
|
||||||
EXPECT_EQ(global_features.provisioning_method, OEMCrypto_OEMCertificate);
|
EXPECT_EQ(global_features.provisioning_method, OEMCrypto_OEMCertificate);
|
||||||
session_->LoadOEMCert(true);
|
session_->LoadOEMCert(true);
|
||||||
session_->GenerateRsaSessionKey(&message_key_, &encrypted_message_key_);
|
session_->GenerateRsaSessionKey();
|
||||||
encryptor_.set_enc_key(message_key_);
|
encryptor_.set_enc_key(session_->session_key());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProvisioningRoundTrip::VerifyRequestSignature(
|
void ProvisioningRoundTrip::VerifyRequestSignature(
|
||||||
const vector<uint8_t>& data, const vector<uint8_t>& generated_signature,
|
const vector<uint8_t>& data, const vector<uint8_t>& generated_signature,
|
||||||
size_t /* core_message_length */) {
|
size_t core_message_length) {
|
||||||
if (global_features.provisioning_method == OEMCrypto_OEMCertificate) {
|
if (keybox_ == nullptr) {
|
||||||
session()->VerifyRsaSignature(data, generated_signature.data(),
|
session()->VerifyRsaSignature(data, generated_signature.data(),
|
||||||
generated_signature.size(), kSign_RSASSA_PSS);
|
generated_signature.size(), kSign_RSASSA_PSS);
|
||||||
} else {
|
} else {
|
||||||
|
// Setup the derived keys using the proto message (ignoring the core
|
||||||
|
// message).
|
||||||
|
ASSERT_LE(core_message_length, data.size());
|
||||||
|
const std::vector<uint8_t> base_message(data.begin() + core_message_length,
|
||||||
|
data.end());
|
||||||
|
session()->GenerateDerivedKeysFromKeybox(*keybox_, base_message);
|
||||||
|
encryptor_ = session()->key_deriver();
|
||||||
|
request_ = base_message;
|
||||||
|
|
||||||
EXPECT_EQ(global_features.provisioning_method, OEMCrypto_Keybox);
|
EXPECT_EQ(global_features.provisioning_method, OEMCrypto_Keybox);
|
||||||
ASSERT_EQ(HMAC_SHA256_SIGNATURE_SIZE, generated_signature.size());
|
ASSERT_EQ(HMAC_SHA256_SIGNATURE_SIZE, generated_signature.size());
|
||||||
std::vector<uint8_t> expected_signature;
|
std::vector<uint8_t> expected_signature;
|
||||||
@@ -403,11 +415,11 @@ void ProvisioningRoundTrip::CreateDefaultResponse() {
|
|||||||
response_data_.rsa_key_length = encoded_rsa_key_.size();
|
response_data_.rsa_key_length = encoded_rsa_key_.size();
|
||||||
}
|
}
|
||||||
response_data_.nonce = session_->nonce();
|
response_data_.nonce = session_->nonce();
|
||||||
if (encrypted_message_key_.size() > 0) {
|
if (session_->enc_session_key().size() > 0) {
|
||||||
ASSERT_LE(encrypted_message_key_.size(), kMaxTestRSAKeyLength);
|
ASSERT_LE(session_->enc_session_key().size(), kMaxTestRSAKeyLength);
|
||||||
memcpy(response_data_.enc_message_key, encrypted_message_key_.data(),
|
memcpy(response_data_.enc_message_key, session_->enc_session_key().data(),
|
||||||
encrypted_message_key_.size());
|
session_->enc_session_key().size());
|
||||||
response_data_.enc_message_key_length = encrypted_message_key_.size();
|
response_data_.enc_message_key_length = session_->enc_session_key().size();
|
||||||
} else {
|
} else {
|
||||||
response_data_.enc_message_key_length = 0;
|
response_data_.enc_message_key_length = 0;
|
||||||
}
|
}
|
||||||
@@ -463,9 +475,6 @@ void ProvisioningRoundTrip::SignResponse() {
|
|||||||
memcpy(encrypted_response_.data() + serialized_core_message_.size(),
|
memcpy(encrypted_response_.data() + serialized_core_message_.size(),
|
||||||
reinterpret_cast<const uint8_t*>(&encrypted_response_data_),
|
reinterpret_cast<const uint8_t*>(&encrypted_response_data_),
|
||||||
sizeof(encrypted_response_data_));
|
sizeof(encrypted_response_data_));
|
||||||
if (global_features.provisioning_method == OEMCrypto_OEMCertificate) {
|
|
||||||
session()->GenerateDerivedKeysFromSessionKey();
|
|
||||||
}
|
|
||||||
session()->key_deriver().ServerSignBuffer(encrypted_response_.data(),
|
session()->key_deriver().ServerSignBuffer(encrypted_response_.data(),
|
||||||
encrypted_response_.size(),
|
encrypted_response_.size(),
|
||||||
&response_signature_);
|
&response_signature_);
|
||||||
@@ -532,10 +541,10 @@ OEMCryptoResult ProvisioningRoundTrip::LoadResponseNoRetry(
|
|||||||
EXPECT_NE(session, nullptr);
|
EXPECT_NE(session, nullptr);
|
||||||
VerifyEncryptAndSignResponseLengths();
|
VerifyEncryptAndSignResponseLengths();
|
||||||
return OEMCrypto_LoadProvisioning(
|
return OEMCrypto_LoadProvisioning(
|
||||||
session->session_id(), encrypted_response_.data(),
|
session->session_id(), request_.data(), request_.size(),
|
||||||
encrypted_response_.size(), serialized_core_message_.size(),
|
encrypted_response_.data(), encrypted_response_.size(),
|
||||||
response_signature_.data(), response_signature_.size(),
|
serialized_core_message_.size(), response_signature_.data(),
|
||||||
wrapped_rsa_key_.data(), wrapped_key_length);
|
response_signature_.size(), wrapped_rsa_key_.data(), wrapped_key_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProvisioningRoundTrip::VerifyLoadFailed() {
|
void ProvisioningRoundTrip::VerifyLoadFailed() {
|
||||||
@@ -754,11 +763,13 @@ OEMCryptoResult Provisioning40CastRoundTrip::LoadResponseNoRetry(
|
|||||||
Session* session, size_t* wrapped_key_length) {
|
Session* session, size_t* wrapped_key_length) {
|
||||||
EXPECT_NE(session, nullptr);
|
EXPECT_NE(session, nullptr);
|
||||||
VerifyEncryptAndSignResponseLengths();
|
VerifyEncryptAndSignResponseLengths();
|
||||||
return OEMCrypto_LoadProvisioning(
|
const std::vector<uint8_t> context = session->GetDefaultContext();
|
||||||
session->session_id(), encrypted_response_.data(),
|
return OEMCrypto_LoadProvisioningCast(
|
||||||
encrypted_response_.size(), serialized_core_message_.size(),
|
session->session_id(), session->enc_session_key().data(),
|
||||||
response_signature_.data(), response_signature_.size(),
|
session->enc_session_key().size(), context.data(), context.size(),
|
||||||
wrapped_rsa_key_.data(), wrapped_key_length);
|
encrypted_response_.data(), encrypted_response_.size(),
|
||||||
|
serialized_core_message_.size(), response_signature_.data(),
|
||||||
|
response_signature_.size(), wrapped_rsa_key_.data(), wrapped_key_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LicenseRoundTrip::VerifyRequestSignature(
|
void LicenseRoundTrip::VerifyRequestSignature(
|
||||||
@@ -1118,6 +1129,8 @@ OEMCryptoResult LicenseRoundTrip::LoadResponse(Session* session,
|
|||||||
core_response_.key_array_length * sizeof(*core_response_.key_array));
|
core_response_.key_array_length * sizeof(*core_response_.key_array));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const vector<uint8_t> context = session->GetDefaultContext();
|
||||||
|
|
||||||
// Some tests adjust the offset to be beyond the length of the message. Here,
|
// Some tests adjust the offset to be beyond the length of the message. Here,
|
||||||
// we create a duplicate of the main message buffer so that these offsets do
|
// we create a duplicate of the main message buffer so that these offsets do
|
||||||
// not point to garbage data. The goal is to make sure OEMCrypto is verifying
|
// not point to garbage data. The goal is to make sure OEMCrypto is verifying
|
||||||
@@ -1134,7 +1147,9 @@ OEMCryptoResult LicenseRoundTrip::LoadResponse(Session* session,
|
|||||||
reinterpret_cast<const uint8_t*>(&encrypted_response_data_) +
|
reinterpret_cast<const uint8_t*>(&encrypted_response_data_) +
|
||||||
sizeof(encrypted_response_data_));
|
sizeof(encrypted_response_data_));
|
||||||
OEMCryptoResult result = OEMCrypto_LoadLicense(
|
OEMCryptoResult result = OEMCrypto_LoadLicense(
|
||||||
session->session_id(), double_message.data(), encrypted_response_.size(),
|
session->session_id(), context.data(), context.size(),
|
||||||
|
session->enc_session_key().data(), session->enc_session_key().size(),
|
||||||
|
double_message.data(), encrypted_response_.size(),
|
||||||
serialized_core_message_.size(), response_signature_.data(),
|
serialized_core_message_.size(), response_signature_.data(),
|
||||||
response_signature_.size());
|
response_signature_.size());
|
||||||
if (verify_keys && result == OEMCrypto_SUCCESS) {
|
if (verify_keys && result == OEMCrypto_SUCCESS) {
|
||||||
@@ -1659,63 +1674,42 @@ void Session::GenerateNonce(int* error_counter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::FillDefaultContext(vector<uint8_t>* mac_context,
|
vector<uint8_t> Session::GetDefaultContext() {
|
||||||
vector<uint8_t>* enc_context) {
|
/* Context string
|
||||||
/* Context strings
|
* This context string is normally created by the CDM layer
|
||||||
* These context strings are normally created by the CDM layer
|
|
||||||
* from a license request message.
|
* from a license request message.
|
||||||
* They are used to test MAC and ENC key generation.
|
* They are used to test MAC and ENC key generation.
|
||||||
*/
|
*/
|
||||||
*mac_context = wvutil::a2b_hex(
|
return wvutil::a2b_hex(
|
||||||
"41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff"
|
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
|
||||||
"de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873"
|
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
|
||||||
"4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a"
|
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
|
||||||
"230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635"
|
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
|
||||||
"34333231180120002a0c31383836373837343035000000000200");
|
"38373430350000");
|
||||||
*enc_context = wvutil::a2b_hex(
|
|
||||||
"454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95"
|
|
||||||
"c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb"
|
|
||||||
"e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408"
|
|
||||||
"0112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231"
|
|
||||||
"180120002a0c31383836373837343035000000000080");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should only be called if the device uses Provisioning 2.0. A failure in
|
// This should only be called if the device uses Provisioning 2.0. A failure in
|
||||||
// this function is probably caused by a bad keybox.
|
// this function is probably caused by a bad keybox.
|
||||||
void Session::GenerateDerivedKeysFromKeybox(
|
void Session::GenerateDerivedKeysFromKeybox(
|
||||||
const wvoec::WidevineKeybox& keybox) {
|
const wvoec::WidevineKeybox& keybox) {
|
||||||
vector<uint8_t> mac_context;
|
return GenerateDerivedKeysFromKeybox(keybox, GetDefaultContext());
|
||||||
vector<uint8_t> enc_context;
|
}
|
||||||
FillDefaultContext(&mac_context, &enc_context);
|
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
void Session::GenerateDerivedKeysFromKeybox(
|
||||||
OEMCrypto_GenerateDerivedKeys(
|
const wvoec::WidevineKeybox& keybox, const std::vector<uint8_t>& context) {
|
||||||
session_id(), mac_context.data(), mac_context.size(),
|
|
||||||
enc_context.data(), enc_context.size()));
|
|
||||||
key_deriver_.DeriveKeys(keybox.device_key_, sizeof(keybox.device_key_),
|
key_deriver_.DeriveKeys(keybox.device_key_, sizeof(keybox.device_key_),
|
||||||
mac_context, enc_context);
|
context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::GenerateDerivedKeysFromSessionKey() {
|
void Session::GenerateDerivedKeysFromSessionKey() {
|
||||||
// Uses test certificate.
|
GenerateDerivedKeysFromSessionKey(GetDefaultContext());
|
||||||
vector<uint8_t> session_key;
|
}
|
||||||
vector<uint8_t> enc_session_key;
|
|
||||||
ASSERT_TRUE(public_rsa_ || public_ec_)
|
|
||||||
<< "No public RSA/ECC key loaded in test code";
|
|
||||||
// A failure here probably indicates that there is something wrong with the
|
|
||||||
// test program and its dependency on BoringSSL.
|
|
||||||
ASSERT_TRUE(GenerateSessionKey(&session_key, &enc_session_key));
|
|
||||||
vector<uint8_t> mac_context;
|
|
||||||
vector<uint8_t> enc_context;
|
|
||||||
FillDefaultContext(&mac_context, &enc_context);
|
|
||||||
// A failure here is probably caused by having the wrong RSA key loaded.
|
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
|
||||||
OEMCrypto_DeriveKeysFromSessionKey(
|
|
||||||
session_id(), enc_session_key.data(), enc_session_key.size(),
|
|
||||||
mac_context.data(), mac_context.size(), enc_context.data(),
|
|
||||||
enc_context.size()));
|
|
||||||
|
|
||||||
key_deriver_.DeriveKeys(session_key.data(), session_key.size(), mac_context,
|
void Session::GenerateDerivedKeysFromSessionKey(
|
||||||
enc_context);
|
const std::vector<uint8_t>& context) {
|
||||||
|
// Uses test certificate.
|
||||||
|
ASSERT_TRUE(GenerateSessionKey());
|
||||||
|
key_deriver_.DeriveKeys(session_key_.data(), session_key_.size(), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::TestDecryptCTR(bool get_fresh_key_handle_first,
|
void Session::TestDecryptCTR(bool get_fresh_key_handle_first,
|
||||||
@@ -2016,19 +2010,17 @@ void Session::VerifySignature(const vector<uint8_t>& message,
|
|||||||
FAIL() << "No public RSA or ECC key loaded in test code";
|
FAIL() << "No public RSA or ECC key loaded in test code";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Session::GenerateRsaSessionKey(vector<uint8_t>* session_key,
|
bool Session::GenerateRsaSessionKey() {
|
||||||
vector<uint8_t>* enc_session_key) {
|
|
||||||
if (!public_rsa_) {
|
if (!public_rsa_) {
|
||||||
cerr << "No public RSA key loaded in test code\n";
|
cerr << "No public RSA key loaded in test code\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*session_key = wvutil::a2b_hex("6fa479c731d2770b6a61a5d1420bb9d1");
|
session_key_ = wvutil::a2b_hex("6fa479c731d2770b6a61a5d1420bb9d1");
|
||||||
*enc_session_key = public_rsa_->EncryptSessionKey(*session_key);
|
enc_session_key_ = public_rsa_->EncryptSessionKey(session_key_);
|
||||||
return !enc_session_key->empty();
|
return !enc_session_key_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Session::GenerateEccSessionKey(vector<uint8_t>* session_key,
|
bool Session::GenerateEccSessionKey() {
|
||||||
vector<uint8_t>* ecdh_public_key_data) {
|
|
||||||
if (!public_ec_) {
|
if (!public_ec_) {
|
||||||
cerr << "No public ECC key loaded in test code\n";
|
cerr << "No public ECC key loaded in test code\n";
|
||||||
return false;
|
return false;
|
||||||
@@ -2043,24 +2035,23 @@ bool Session::GenerateEccSessionKey(vector<uint8_t>* session_key,
|
|||||||
<< util::EccCurveToString(curve) << std::endl;
|
<< util::EccCurveToString(curve) << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*session_key = server_ephemeral_keys_[curve]->DeriveSessionKey(*public_ec_);
|
session_key_ = server_ephemeral_keys_[curve]->DeriveSessionKey(*public_ec_);
|
||||||
if (session_key->empty()) {
|
if (session_key_.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*ecdh_public_key_data = server_ephemeral_keys_[curve]->SerializeAsPublicKey();
|
enc_session_key_ = server_ephemeral_keys_[curve]->SerializeAsPublicKey();
|
||||||
if (ecdh_public_key_data->empty()) {
|
if (enc_session_key_.empty()) {
|
||||||
session_key->clear();
|
session_key_.clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Session::GenerateSessionKey(vector<uint8_t>* session_key,
|
bool Session::GenerateSessionKey() {
|
||||||
vector<uint8_t>* key_material) {
|
|
||||||
if (public_rsa_ != nullptr) {
|
if (public_rsa_ != nullptr) {
|
||||||
return GenerateRsaSessionKey(session_key, key_material);
|
return GenerateRsaSessionKey();
|
||||||
} else if (public_ec_ != nullptr) {
|
} else if (public_ec_ != nullptr) {
|
||||||
return GenerateEccSessionKey(session_key, key_material);
|
return GenerateEccSessionKey();
|
||||||
}
|
}
|
||||||
cerr << "No public RSA or ECC key loaded in test code\n";
|
cerr << "No public RSA or ECC key loaded in test code\n";
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ class ProvisioningRoundTrip
|
|||||||
const std::vector<uint8_t>& encoded_rsa_key)
|
const std::vector<uint8_t>& encoded_rsa_key)
|
||||||
: RoundTrip(session),
|
: RoundTrip(session),
|
||||||
allowed_schemes_(kSign_RSASSA_PSS),
|
allowed_schemes_(kSign_RSASSA_PSS),
|
||||||
encryptor_(),
|
keybox_(nullptr),
|
||||||
encoded_rsa_key_(encoded_rsa_key) {}
|
encoded_rsa_key_(encoded_rsa_key) {}
|
||||||
// Prepare the session for signing the request.
|
// Prepare the session for signing the request.
|
||||||
virtual void PrepareSession(const wvoec::WidevineKeybox& keybox);
|
virtual void PrepareSession(const wvoec::WidevineKeybox& keybox);
|
||||||
@@ -317,9 +317,9 @@ class ProvisioningRoundTrip
|
|||||||
|
|
||||||
uint32_t allowed_schemes_;
|
uint32_t allowed_schemes_;
|
||||||
Encryptor encryptor_;
|
Encryptor encryptor_;
|
||||||
|
std::vector<uint8_t> request_;
|
||||||
|
const wvoec::WidevineKeybox* keybox_;
|
||||||
// The message key used for Prov 3.0.
|
// The message key used for Prov 3.0.
|
||||||
std::vector<uint8_t> message_key_;
|
|
||||||
std::vector<uint8_t> encrypted_message_key_;
|
|
||||||
std::vector<uint8_t> encoded_rsa_key_;
|
std::vector<uint8_t> encoded_rsa_key_;
|
||||||
std::vector<uint8_t> wrapped_rsa_key_;
|
std::vector<uint8_t> wrapped_rsa_key_;
|
||||||
};
|
};
|
||||||
@@ -673,15 +673,17 @@ class Session {
|
|||||||
// and try again if a nonce flood has been detected. If error_counter is
|
// and try again if a nonce flood has been detected. If error_counter is
|
||||||
// not null, it will be incremented when a nonce flood is detected.
|
// not null, it will be incremented when a nonce flood is detected.
|
||||||
void GenerateNonce(int* error_counter = nullptr);
|
void GenerateNonce(int* error_counter = nullptr);
|
||||||
// Fill the vectors with test context which generate known mac and enc keys.
|
// Fill the vector with test context which generate known mac and enc keys.
|
||||||
void FillDefaultContext(vector<uint8_t>* mac_context,
|
std::vector<uint8_t> GetDefaultContext();
|
||||||
vector<uint8_t>* enc_context);
|
|
||||||
// Generate known mac and enc keys using OEMCrypto_GenerateDerivedKeys and
|
// Generate known mac and enc keys using OEMCrypto_GenerateDerivedKeys and
|
||||||
// also fill out enc_key_, mac_key_server_, and mac_key_client_.
|
// also fill out enc_key_, mac_key_server_, and mac_key_client_.
|
||||||
void GenerateDerivedKeysFromKeybox(const wvoec::WidevineKeybox& keybox);
|
void GenerateDerivedKeysFromKeybox(const wvoec::WidevineKeybox& keybox);
|
||||||
|
void GenerateDerivedKeysFromKeybox(const wvoec::WidevineKeybox& keybox,
|
||||||
|
const std::vector<uint8_t>& context);
|
||||||
// Generate known mac and enc keys using OEMCrypto_DeriveKeysFromSessionKey
|
// Generate known mac and enc keys using OEMCrypto_DeriveKeysFromSessionKey
|
||||||
// and also fill out enc_key_, mac_key_server_, and mac_key_client_.
|
// and also fill out enc_key_, mac_key_server_, and mac_key_client_.
|
||||||
void GenerateDerivedKeysFromSessionKey();
|
void GenerateDerivedKeysFromSessionKey();
|
||||||
|
void GenerateDerivedKeysFromSessionKey(const std::vector<uint8_t>& context);
|
||||||
// Encrypt some data and pass to OEMCrypto_DecryptCENC to verify decryption.
|
// Encrypt some data and pass to OEMCrypto_DecryptCENC to verify decryption.
|
||||||
void TestDecryptCTR(bool get_fresh_key_handle_first = true,
|
void TestDecryptCTR(bool get_fresh_key_handle_first = true,
|
||||||
OEMCryptoResult expected_result = OEMCrypto_SUCCESS,
|
OEMCryptoResult expected_result = OEMCrypto_SUCCESS,
|
||||||
@@ -747,17 +749,14 @@ class Session {
|
|||||||
// Encrypts a known session key with public_rsa_ for use in future calls to
|
// Encrypts a known session key with public_rsa_ for use in future calls to
|
||||||
// OEMCrypto_DeriveKeysFromSessionKey or OEMCrypto_RewrapDeviceRSAKey30.
|
// OEMCrypto_DeriveKeysFromSessionKey or OEMCrypto_RewrapDeviceRSAKey30.
|
||||||
// The unencrypted session key is stored in session_key.
|
// The unencrypted session key is stored in session_key.
|
||||||
bool GenerateRsaSessionKey(vector<uint8_t>* session_key,
|
bool GenerateRsaSessionKey();
|
||||||
vector<uint8_t>* enc_session_key);
|
|
||||||
// Derives a session key with public_ec_ and a ephemeral "server" ECC key
|
// Derives a session key with public_ec_ and a ephemeral "server" ECC key
|
||||||
// for use in future calls to OEMCrypto_DeriveKeysFromSessionKey.
|
// for use in future calls to OEMCrypto_DeriveKeysFromSessionKey.
|
||||||
// The unencrypted session key is stored in session_key.
|
// The unencrypted session key is stored in session_key.
|
||||||
bool GenerateEccSessionKey(vector<uint8_t>* session_key,
|
bool GenerateEccSessionKey();
|
||||||
vector<uint8_t>* ecdh_public_key_data);
|
|
||||||
// Based on the key type installed, call GenerateRsaSessionKey or
|
// Based on the key type installed, call GenerateRsaSessionKey or
|
||||||
// GenerateEccSessionKey.
|
// GenerateEccSessionKey.
|
||||||
bool GenerateSessionKey(vector<uint8_t>* session_key,
|
bool GenerateSessionKey();
|
||||||
vector<uint8_t>* key_material);
|
|
||||||
|
|
||||||
// Calls OEMCrypto_RewrapDeviceRSAKey30 with the given provisioning response
|
// Calls OEMCrypto_RewrapDeviceRSAKey30 with the given provisioning response
|
||||||
// message. If force is true, we assert that the key loads successfully.
|
// message. If force is true, we assert that the key loads successfully.
|
||||||
@@ -840,6 +839,11 @@ class Session {
|
|||||||
// functions.
|
// functions.
|
||||||
vector<uint8_t>& key_handle() { return key_handle_; }
|
vector<uint8_t>& key_handle() { return key_handle_; }
|
||||||
|
|
||||||
|
const std::vector<uint8_t>& session_key() const { return session_key_; }
|
||||||
|
const std::vector<uint8_t>& enc_session_key() const {
|
||||||
|
return enc_session_key_;
|
||||||
|
}
|
||||||
|
|
||||||
const KeyDeriver& key_deriver() const { return key_deriver_; }
|
const KeyDeriver& key_deriver() const { return key_deriver_; }
|
||||||
void set_mac_keys(const uint8_t* mac_keys) {
|
void set_mac_keys(const uint8_t* mac_keys) {
|
||||||
key_deriver_.set_mac_keys(mac_keys);
|
key_deriver_.set_mac_keys(mac_keys);
|
||||||
@@ -882,6 +886,8 @@ class Session {
|
|||||||
vector<uint8_t> pst_report_buffer_;
|
vector<uint8_t> pst_report_buffer_;
|
||||||
MessageData license_ = {};
|
MessageData license_ = {};
|
||||||
vector<uint8_t> key_handle_;
|
vector<uint8_t> key_handle_;
|
||||||
|
std::vector<uint8_t> session_key_;
|
||||||
|
std::vector<uint8_t> enc_session_key_;
|
||||||
|
|
||||||
vector<uint8_t> encrypted_usage_entry_;
|
vector<uint8_t> encrypted_usage_entry_;
|
||||||
uint32_t usage_entry_number_ = 0;
|
uint32_t usage_entry_number_ = 0;
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ TEST_F(OEMCryptoLoadsCertificateAlternates, ForbidUseAsDRMCert) {
|
|||||||
if (key_loaded_) {
|
if (key_loaded_) {
|
||||||
// The other padding scheme should fail.
|
// The other padding scheme should fail.
|
||||||
DisallowForbiddenPaddingDRMKey(kSign_RSASSA_PSS, 83);
|
DisallowForbiddenPaddingDRMKey(kSign_RSASSA_PSS, 83);
|
||||||
DisallowDeriveKeys();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,26 +51,6 @@ class OEMCryptoLoadsCertificateAlternates : public OEMCryptoLoadsCertificate {
|
|||||||
licenseRequest, signature.data(), signature_length, scheme));
|
licenseRequest, signature.data(), signature_length, scheme));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisallowDeriveKeys() {
|
|
||||||
Session s;
|
|
||||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
|
||||||
ASSERT_NO_FATAL_FAILURE(s.LoadWrappedRsaDrmKey(wrapped_drm_key_));
|
|
||||||
s.GenerateNonce();
|
|
||||||
vector<uint8_t> session_key;
|
|
||||||
vector<uint8_t> enc_session_key;
|
|
||||||
ASSERT_NO_FATAL_FAILURE(s.SetRsaPublicKeyFromPrivateKeyInfo(
|
|
||||||
encoded_rsa_key_.data(), encoded_rsa_key_.size()));
|
|
||||||
ASSERT_TRUE(s.GenerateRsaSessionKey(&session_key, &enc_session_key));
|
|
||||||
vector<uint8_t> mac_context;
|
|
||||||
vector<uint8_t> enc_context;
|
|
||||||
s.FillDefaultContext(&mac_context, &enc_context);
|
|
||||||
ASSERT_NE(OEMCrypto_SUCCESS,
|
|
||||||
OEMCrypto_DeriveKeysFromSessionKey(
|
|
||||||
s.session_id(), enc_session_key.data(),
|
|
||||||
enc_session_key.size(), mac_context.data(),
|
|
||||||
mac_context.size(), enc_context.data(), enc_context.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If force is true, we assert that the key loads successfully.
|
// If force is true, we assert that the key loads successfully.
|
||||||
void LoadCastCertificateKey(bool force) {
|
void LoadCastCertificateKey(bool force) {
|
||||||
if (!wvoec::global_features.cast_receiver) {
|
if (!wvoec::global_features.cast_receiver) {
|
||||||
|
|||||||
@@ -472,9 +472,12 @@ TEST_P(OEMCryptoLicenseTest, LoadKeyUnalignedMessageAPI16) {
|
|||||||
license_messages_.encrypted_response_buffer().end());
|
license_messages_.encrypted_response_buffer().end());
|
||||||
// Thus, buffer[offset] is NOT word aligned.
|
// Thus, buffer[offset] is NOT word aligned.
|
||||||
const uint8_t* unaligned_message = &buffer[offset];
|
const uint8_t* unaligned_message = &buffer[offset];
|
||||||
|
const std::vector<uint8_t> context = session_.GetDefaultContext();
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_LoadLicense(
|
OEMCrypto_LoadLicense(
|
||||||
session_.session_id(), unaligned_message,
|
session_.session_id(), context.data(), context.size(),
|
||||||
|
session_.enc_session_key().data(),
|
||||||
|
session_.enc_session_key().size(), unaligned_message,
|
||||||
license_messages_.encrypted_response_buffer().size(),
|
license_messages_.encrypted_response_buffer().size(),
|
||||||
license_messages_.serialized_core_message().size(),
|
license_messages_.serialized_core_message().size(),
|
||||||
license_messages_.response_signature().data(),
|
license_messages_.response_signature().data(),
|
||||||
|
|||||||
@@ -67,24 +67,6 @@ TEST_F(OEMCryptoKeyboxTest, ProductionKeyboxValid) {
|
|||||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid());
|
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This tests GenerateDerivedKeys with an 8k context.
|
|
||||||
TEST_F(OEMCryptoKeyboxTest, GenerateDerivedKeysFromKeyboxLargeBuffer) {
|
|
||||||
Session s;
|
|
||||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
|
||||||
const size_t max_size = GetResourceValue(kLargeMessageSize);
|
|
||||||
vector<uint8_t> mac_context(max_size);
|
|
||||||
vector<uint8_t> enc_context(max_size);
|
|
||||||
// Stripe the data so the two vectors are not identical, and not all zeroes.
|
|
||||||
for (size_t i = 0; i < max_size; i++) {
|
|
||||||
mac_context[i] = i % 0x100;
|
|
||||||
enc_context[i] = (3 * i) % 0x100;
|
|
||||||
}
|
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
|
||||||
OEMCrypto_GenerateDerivedKeys(
|
|
||||||
s.session_id(), mac_context.data(), mac_context.size(),
|
|
||||||
enc_context.data(), enc_context.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// This verifies that the device really does claim to have a certificate.
|
// This verifies that the device really does claim to have a certificate.
|
||||||
// It should be filtered out for devices that have a keybox.
|
// It should be filtered out for devices that have a keybox.
|
||||||
TEST_F(OEMCryptoProv30Test, DeviceClaimsOEMCertificate) {
|
TEST_F(OEMCryptoProv30Test, DeviceClaimsOEMCertificate) {
|
||||||
@@ -164,7 +146,6 @@ TEST_F(OEMCryptoProv30Test, GetCertOnlyAPI16) {
|
|||||||
// Derive keys from the session key -- this should use the DRM Cert's key.
|
// Derive keys from the session key -- this should use the DRM Cert's key.
|
||||||
// It should NOT use the OEM Private key because that key should not have
|
// It should NOT use the OEM Private key because that key should not have
|
||||||
// been loaded.
|
// been loaded.
|
||||||
ASSERT_NO_FATAL_FAILURE(s.GenerateDerivedKeysFromSessionKey());
|
|
||||||
// Now fill a message and try to load it.
|
// Now fill a message and try to load it.
|
||||||
LicenseRoundTrip license_messages(&s);
|
LicenseRoundTrip license_messages(&s);
|
||||||
license_messages.set_control(0);
|
license_messages.set_control(0);
|
||||||
@@ -745,14 +726,8 @@ TEST_F(OEMCryptoLoadsCertificate, SignProvisioningRequest) {
|
|||||||
GTEST_SKIP() << "Test for non Prov 4.0 devices only.";
|
GTEST_SKIP() << "Test for non Prov 4.0 devices only.";
|
||||||
}
|
}
|
||||||
Session s;
|
Session s;
|
||||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
|
||||||
if (global_features.provisioning_method == OEMCrypto_OEMCertificate) {
|
|
||||||
s.LoadOEMCert(true);
|
|
||||||
} else {
|
|
||||||
EXPECT_EQ(global_features.provisioning_method, OEMCrypto_Keybox);
|
|
||||||
s.GenerateDerivedKeysFromKeybox(keybox_);
|
|
||||||
}
|
|
||||||
ProvisioningRoundTrip provisioning_messages(&s, encoded_rsa_key_);
|
ProvisioningRoundTrip provisioning_messages(&s, encoded_rsa_key_);
|
||||||
|
ASSERT_NO_FATAL_FAILURE(provisioning_messages.PrepareSession(keybox_));
|
||||||
ASSERT_NO_FATAL_FAILURE(provisioning_messages.SignAndVerifyRequest());
|
ASSERT_NO_FATAL_FAILURE(provisioning_messages.SignAndVerifyRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -764,16 +739,10 @@ TEST_F(OEMCryptoLoadsCertificate, SignLargeProvisioningRequestAPI16) {
|
|||||||
GTEST_SKIP() << "Test for non Prov 4.0 devices only.";
|
GTEST_SKIP() << "Test for non Prov 4.0 devices only.";
|
||||||
}
|
}
|
||||||
Session s;
|
Session s;
|
||||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
|
||||||
if (global_features.provisioning_method == OEMCrypto_OEMCertificate) {
|
|
||||||
s.LoadOEMCert(true);
|
|
||||||
} else {
|
|
||||||
EXPECT_EQ(global_features.provisioning_method, OEMCrypto_Keybox);
|
|
||||||
s.GenerateDerivedKeysFromKeybox(keybox_);
|
|
||||||
}
|
|
||||||
ProvisioningRoundTrip provisioning_messages(&s, encoded_rsa_key_);
|
ProvisioningRoundTrip provisioning_messages(&s, encoded_rsa_key_);
|
||||||
const size_t max_size = GetResourceValue(kLargeMessageSize);
|
const size_t max_size = GetResourceValue(kLargeMessageSize);
|
||||||
provisioning_messages.set_message_size(max_size);
|
provisioning_messages.set_message_size(max_size);
|
||||||
|
ASSERT_NO_FATAL_FAILURE(provisioning_messages.PrepareSession(keybox_));
|
||||||
ASSERT_NO_FATAL_FAILURE(provisioning_messages.SignAndVerifyRequest());
|
ASSERT_NO_FATAL_FAILURE(provisioning_messages.SignAndVerifyRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -788,7 +757,7 @@ TEST_F(OEMCryptoLoadsCertificate, CertificateProvision) {
|
|||||||
}
|
}
|
||||||
Session s;
|
Session s;
|
||||||
ProvisioningRoundTrip provisioning_messages(&s, encoded_rsa_key_);
|
ProvisioningRoundTrip provisioning_messages(&s, encoded_rsa_key_);
|
||||||
provisioning_messages.PrepareSession(keybox_);
|
ASSERT_NO_FATAL_FAILURE(provisioning_messages.PrepareSession(keybox_));
|
||||||
ASSERT_NO_FATAL_FAILURE(provisioning_messages.SignAndVerifyRequest());
|
ASSERT_NO_FATAL_FAILURE(provisioning_messages.SignAndVerifyRequest());
|
||||||
ASSERT_NO_FATAL_FAILURE(provisioning_messages.CreateDefaultResponse());
|
ASSERT_NO_FATAL_FAILURE(provisioning_messages.CreateDefaultResponse());
|
||||||
ASSERT_NO_FATAL_FAILURE(provisioning_messages.EncryptAndSignResponse());
|
ASSERT_NO_FATAL_FAILURE(provisioning_messages.EncryptAndSignResponse());
|
||||||
@@ -1326,41 +1295,17 @@ TEST_F(OEMCryptoLoadsCertificate, RSAPerformance) {
|
|||||||
Session s;
|
Session s;
|
||||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||||
ASSERT_NO_FATAL_FAILURE(s.LoadWrappedRsaDrmKey(wrapped_drm_key_));
|
ASSERT_NO_FATAL_FAILURE(s.LoadWrappedRsaDrmKey(wrapped_drm_key_));
|
||||||
vector<uint8_t> session_key;
|
|
||||||
vector<uint8_t> enc_session_key;
|
|
||||||
ASSERT_NO_FATAL_FAILURE(s.SetRsaPublicKeyFromPrivateKeyInfo(
|
ASSERT_NO_FATAL_FAILURE(s.SetRsaPublicKeyFromPrivateKeyInfo(
|
||||||
encoded_rsa_key_.data(), encoded_rsa_key_.size()));
|
encoded_rsa_key_.data(), encoded_rsa_key_.size()));
|
||||||
ASSERT_TRUE(s.GenerateRsaSessionKey(&session_key, &enc_session_key));
|
|
||||||
vector<uint8_t> mac_context;
|
|
||||||
vector<uint8_t> enc_context;
|
|
||||||
s.FillDefaultContext(&mac_context, &enc_context);
|
|
||||||
|
|
||||||
enc_session_key = wvutil::a2b_hex(
|
LicenseRoundTrip license_messages(&s);
|
||||||
"7789c619aa3b9fa3c0a53f57a4abc6"
|
license_messages.SignAndVerifyRequest();
|
||||||
"02157c8aa57e3c6fb450b0bea22667fb"
|
license_messages.CreateDefaultResponse();
|
||||||
"0c3200f9d9d618e397837c720dc2dadf"
|
|
||||||
"486f33590744b2a4e54ca134ae7dbf74"
|
|
||||||
"434c2fcf6b525f3e132262f05ea3b3c1"
|
|
||||||
"198595c0e52b573335b2e8a3debd0d0d"
|
|
||||||
"d0306f8fcdde4e76476be71342957251"
|
|
||||||
"e1688c9ca6c1c34ed056d3b989394160"
|
|
||||||
"cf6937e5ce4d39cc73d11a2e93da21a2"
|
|
||||||
"fa019d246c852fe960095b32f120c3c2"
|
|
||||||
"7085f7b64aac344a68d607c0768676ce"
|
|
||||||
"d4c5b2d057f7601921b453a451e1dea0"
|
|
||||||
"843ebfef628d9af2784d68e86b730476"
|
|
||||||
"e136dfe19989de4be30a4e7878efcde5"
|
|
||||||
"ad2b1254f80c0c5dd3cf111b56572217"
|
|
||||||
"b9f58fc1dacbf74b59d354a1e62cfa0e"
|
|
||||||
"bf");
|
|
||||||
start_time = clock.now();
|
start_time = clock.now();
|
||||||
count = 0;
|
count = 0;
|
||||||
do {
|
do {
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
license_messages.LoadResponse(&s, /* verify_keys= */ false);
|
||||||
OEMCrypto_DeriveKeysFromSessionKey(
|
|
||||||
s.session_id(), enc_session_key.data(),
|
|
||||||
enc_session_key.size(), mac_context.data(),
|
|
||||||
mac_context.size(), enc_context.data(), enc_context.size()));
|
|
||||||
count++;
|
count++;
|
||||||
} while (clock.now() - start_time < kTestDuration);
|
} while (clock.now() - start_time < kTestDuration);
|
||||||
delta_time = clock.now() - start_time;
|
delta_time = clock.now() - start_time;
|
||||||
@@ -1376,24 +1321,4 @@ TEST_F(OEMCryptoLoadsCertificate, RSAPerformance) {
|
|||||||
derive_keys_time);
|
derive_keys_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test DeriveKeysFromSessionKey using the maximum size for the HMAC context.
|
|
||||||
TEST_F(OEMCryptoUsesCertificate, GenerateDerivedKeysLargeBuffer) {
|
|
||||||
vector<uint8_t> session_key;
|
|
||||||
vector<uint8_t> enc_session_key;
|
|
||||||
ASSERT_TRUE(session_.GenerateSessionKey(&session_key, &enc_session_key));
|
|
||||||
const size_t max_size = GetResourceValue(kLargeMessageSize);
|
|
||||||
vector<uint8_t> mac_context(max_size);
|
|
||||||
vector<uint8_t> enc_context(max_size);
|
|
||||||
// Stripe the data so the two vectors are not identical, and not all zeroes.
|
|
||||||
for (size_t i = 0; i < max_size; i++) {
|
|
||||||
mac_context[i] = i % 0x100;
|
|
||||||
enc_context[i] = (3 * i) % 0x100;
|
|
||||||
}
|
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
|
||||||
OEMCrypto_DeriveKeysFromSessionKey(
|
|
||||||
session_.session_id(), enc_session_key.data(),
|
|
||||||
enc_session_key.size(), mac_context.data(), mac_context.size(),
|
|
||||||
enc_context.data(), enc_context.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace wvoec
|
} // namespace wvoec
|
||||||
|
|||||||
@@ -173,15 +173,11 @@ class OTAKeyboxProvisioningTest : public ::testing::Test, public SessionUtil {
|
|||||||
TEST_F(OTAKeyboxProvisioningTest, BasicTest) {
|
TEST_F(OTAKeyboxProvisioningTest, BasicTest) {
|
||||||
OEMCryptoResult result = OEMCrypto_IsKeyboxValid();
|
OEMCryptoResult result = OEMCrypto_IsKeyboxValid();
|
||||||
if (result == OEMCrypto_SUCCESS) {
|
if (result == OEMCrypto_SUCCESS) {
|
||||||
cout << " "
|
GTEST_SKIP() << "Keybox valid after initialization. Skipping rest of test.";
|
||||||
<< "Keybox valid after initialization. Skipping rest of test." << endl;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (result != OEMCrypto_ERROR_NEEDS_KEYBOX_PROVISIONING) {
|
if (result != OEMCrypto_ERROR_NEEDS_KEYBOX_PROVISIONING) {
|
||||||
cout << " "
|
GTEST_SKIP()
|
||||||
<< "OTA Keybox functions not supported. Skipping rest of test."
|
<< "OTA Keybox functions not supported. Skipping rest of test.";
|
||||||
<< endl;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
cout << " "
|
cout << " "
|
||||||
<< "OTA Keybox functions supported. Device needs provisioning." << endl;
|
<< "OTA Keybox functions supported. Device needs provisioning." << endl;
|
||||||
@@ -235,28 +231,11 @@ TEST_F(OTAKeyboxProvisioningTest, BasicTest) {
|
|||||||
const std::vector<uint8_t> model_key = GetModelKey(device_id);
|
const std::vector<uint8_t> model_key = GetModelKey(device_id);
|
||||||
#endif
|
#endif
|
||||||
// The server should derive the same set of keys as the client.
|
// The server should derive the same set of keys as the client.
|
||||||
const std::string mac_label = "WV_SIGN";
|
|
||||||
std::vector<uint8_t> mac_context(mac_label.begin(), mac_label.end());
|
|
||||||
mac_context.push_back(0);
|
|
||||||
std::copy(cert.begin(), cert.end(), std::back_inserter(mac_context));
|
|
||||||
std::copy(device_id.begin(), device_id.end(),
|
|
||||||
std::back_inserter(mac_context));
|
|
||||||
uint32_t bit_size = MAC_KEY_SIZE * 8 * 2;
|
|
||||||
std::string bit_size_string = wvutil::EncodeUint32(bit_size);
|
|
||||||
std::copy(bit_size_string.begin(), bit_size_string.end(),
|
|
||||||
std::back_inserter(mac_context));
|
|
||||||
std::string enc_label = "WV_ENCRYPT";
|
|
||||||
std::vector<uint8_t> enc_context(enc_label.begin(), enc_label.end());
|
|
||||||
enc_context.push_back(0);
|
|
||||||
std::copy(cert.begin(), cert.end(), std::back_inserter(enc_context));
|
|
||||||
std::copy(device_id.begin(), device_id.end(),
|
|
||||||
std::back_inserter(enc_context));
|
|
||||||
bit_size = KEY_SIZE * 8;
|
|
||||||
bit_size_string = wvutil::EncodeUint32(bit_size);
|
|
||||||
std::copy(bit_size_string.begin(), bit_size_string.end(),
|
|
||||||
std::back_inserter(enc_context));
|
|
||||||
KeyDeriver keys;
|
KeyDeriver keys;
|
||||||
keys.DeriveKeys(model_key.data(), model_key.size(), mac_context, enc_context);
|
std::vector<uint8_t> context = cert;
|
||||||
|
context.insert(context.end(), device_id.begin(), device_id.end());
|
||||||
|
keys.DeriveKeys(model_key.data(), model_key.size(), context, "WV_SIGN",
|
||||||
|
"WV_ENCRYPT");
|
||||||
const std::vector<uint8_t> message(
|
const std::vector<uint8_t> message(
|
||||||
request.data(),
|
request.data(),
|
||||||
request.data() + request.size() - HMAC_SHA256_SIGNATURE_SIZE);
|
request.data() + request.size() - HMAC_SHA256_SIGNATURE_SIZE);
|
||||||
|
|||||||
Reference in New Issue
Block a user