|
|
|
|
@@ -697,6 +697,63 @@ bool SessionContext::LoadRSAKey(const uint8_t* pkcs8_rsa_key,
|
|
|
|
|
return rsa_key_.LoadPkcs8RsaKey(pkcs8_rsa_key, rsa_key_length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OEMCryptoResult SessionContext::AllowKeyUse(const std::string& log_string,
|
|
|
|
|
uint32_t use_type,
|
|
|
|
|
OEMCryptoBufferType buffer_type) {
|
|
|
|
|
const KeyControlBlock& control = current_content_key()->control();
|
|
|
|
|
if (use_type && (!(control.control_bits() & use_type))) {
|
|
|
|
|
LOGE("[%s(): control bit says not allowed.", log_string.c_str());
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
if (control.control_bits() & kControlDataPathSecure) {
|
|
|
|
|
if (!ce_->config_closed_platform() &&
|
|
|
|
|
buffer_type == OEMCrypto_BufferType_Clear) {
|
|
|
|
|
LOGE("[%s(): Secure key with insecure buffer]", log_string.c_str());
|
|
|
|
|
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (control.control_bits() & kControlReplayMask) {
|
|
|
|
|
if (!IsUsageEntryValid()) {
|
|
|
|
|
LOGE("[%s(): usage entry not valid]", log_string.c_str());
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (control.duration() > 0) {
|
|
|
|
|
if (control.duration() < CurrentTimer()) {
|
|
|
|
|
LOGE("[%s(): key expired.", log_string.c_str());
|
|
|
|
|
return OEMCrypto_ERROR_KEY_EXPIRED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!ce_->config_local_display_only()) {
|
|
|
|
|
// Only look at HDCP and Analog restrictions if the display is non-local.
|
|
|
|
|
if (control.control_bits() & kControlHDCPRequired) {
|
|
|
|
|
uint8_t required_hdcp =
|
|
|
|
|
(control.control_bits() & kControlHDCPVersionMask) >>
|
|
|
|
|
kControlHDCPVersionShift;
|
|
|
|
|
// For reference implementation, we pretend we can handle the current
|
|
|
|
|
// HDCP version.
|
|
|
|
|
if (required_hdcp > ce_->config_current_hdcp_capability() ||
|
|
|
|
|
ce_->config_current_hdcp_capability() == 0) {
|
|
|
|
|
return OEMCrypto_ERROR_INSUFFICIENT_HDCP;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (control.control_bits() & kControlSRMVersionRequired) {
|
|
|
|
|
LOGE("[%s(): control bit says SRM version required.",
|
|
|
|
|
log_string.c_str());
|
|
|
|
|
return OEMCrypto_ERROR_INSUFFICIENT_HDCP;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!ce_->config_local_display_only()
|
|
|
|
|
|| buffer_type == OEMCrypto_BufferType_Clear) {
|
|
|
|
|
if (control.control_bits() & kControlDisableAnalogOutput) {
|
|
|
|
|
LOGE("[%s(): control bit says disable analog.",
|
|
|
|
|
log_string.c_str());
|
|
|
|
|
return OEMCrypto_ERROR_ANALOG_OUTPUT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return OEMCrypto_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OEMCryptoResult SessionContext::Generic_Encrypt(const uint8_t* in_buffer,
|
|
|
|
|
size_t buffer_length,
|
|
|
|
|
const uint8_t* iv,
|
|
|
|
|
@@ -708,28 +765,14 @@ OEMCryptoResult SessionContext::Generic_Encrypt(const uint8_t* in_buffer,
|
|
|
|
|
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
|
|
|
|
}
|
|
|
|
|
const std::vector<uint8_t>& key = current_content_key()->value();
|
|
|
|
|
const KeyControlBlock& control = current_content_key()->control();
|
|
|
|
|
// Set the AES key.
|
|
|
|
|
if (static_cast<int>(key.size()) != AES_BLOCK_SIZE) {
|
|
|
|
|
LOGE("[Generic_Encrypt(): CONTENT_KEY has wrong size: %d", key.size());
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
if (!(control.control_bits() & kControlAllowEncrypt)) {
|
|
|
|
|
LOGE("[Generic_Encrypt(): control bit says not allowed.");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
if (control.duration() > 0) {
|
|
|
|
|
if (control.duration() < CurrentTimer()) {
|
|
|
|
|
LOGE("[Generic_Encrypt(): key expired.");
|
|
|
|
|
return OEMCrypto_ERROR_KEY_EXPIRED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (control.control_bits() & kControlReplayMask) {
|
|
|
|
|
if (!IsUsageEntryValid()) {
|
|
|
|
|
LOGE("[Generic_Encrypt(): usage entry not valid]");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
OEMCryptoResult result = AllowKeyUse("Generic_Encrypt", kControlAllowEncrypt,
|
|
|
|
|
OEMCrypto_BufferType_Clear);
|
|
|
|
|
if (result != OEMCrypto_SUCCESS) return result;
|
|
|
|
|
if (algorithm != OEMCrypto_AES_CBC_128_NO_PADDING) {
|
|
|
|
|
LOGE("[Generic_Encrypt(): algorithm bad.");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
@@ -762,34 +805,15 @@ OEMCryptoResult SessionContext::Generic_Decrypt(const uint8_t* in_buffer,
|
|
|
|
|
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
|
|
|
|
}
|
|
|
|
|
const std::vector<uint8_t>& key = current_content_key()->value();
|
|
|
|
|
const KeyControlBlock& control = current_content_key()->control();
|
|
|
|
|
// Set the AES key.
|
|
|
|
|
if (static_cast<int>(key.size()) != AES_BLOCK_SIZE) {
|
|
|
|
|
LOGE("[Generic_Decrypt(): CONTENT_KEY has wrong size.");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
if (!(control.control_bits() & kControlAllowDecrypt)) {
|
|
|
|
|
LOGE("[Generic_Decrypt(): control bit says not allowed.");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
if (control.control_bits() & kControlDataPathSecure) {
|
|
|
|
|
if (!ce_->config_closed_platform()) {
|
|
|
|
|
LOGE("[Generic_Decrypt(): control bit says secure path only.");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (control.duration() > 0) {
|
|
|
|
|
if (control.duration() < CurrentTimer()) {
|
|
|
|
|
LOGE("[Generic_Decrypt(): key expired.");
|
|
|
|
|
return OEMCrypto_ERROR_KEY_EXPIRED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (control.control_bits() & kControlReplayMask) {
|
|
|
|
|
if (!IsUsageEntryValid()) {
|
|
|
|
|
LOGE("[Generic_Decrypt(): usage entry not valid]");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
OEMCryptoResult result = AllowKeyUse("Generic_Decrypt", kControlAllowDecrypt,
|
|
|
|
|
OEMCrypto_BufferType_Clear);
|
|
|
|
|
if (result != OEMCrypto_SUCCESS) return result;
|
|
|
|
|
|
|
|
|
|
if (algorithm != OEMCrypto_AES_CBC_128_NO_PADDING) {
|
|
|
|
|
LOGE("[Generic_Decrypt(): bad algorithm.");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
@@ -827,27 +851,13 @@ OEMCryptoResult SessionContext::Generic_Sign(const uint8_t* in_buffer,
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
const std::vector<uint8_t>& key = current_content_key()->value();
|
|
|
|
|
const KeyControlBlock& control = current_content_key()->control();
|
|
|
|
|
if (static_cast<int>(key.size()) != SHA256_DIGEST_LENGTH) {
|
|
|
|
|
LOGE("[Generic_Sign(): CONTENT_KEY has wrong size; %d", key.size());
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
if (!(control.control_bits() & kControlAllowSign)) {
|
|
|
|
|
LOGE("[Generic_Sign(): control bit says not allowed.");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
if (control.duration() > 0) {
|
|
|
|
|
if (control.duration() < CurrentTimer()) {
|
|
|
|
|
LOGE("[Generic_Sign(): key expired.");
|
|
|
|
|
return OEMCrypto_ERROR_KEY_EXPIRED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (control.control_bits() & kControlReplayMask) {
|
|
|
|
|
if (!IsUsageEntryValid()) {
|
|
|
|
|
LOGE("[Generic_Sign(): usage entry not valid]");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
OEMCryptoResult result = AllowKeyUse("Generic_Sign", kControlAllowSign,
|
|
|
|
|
OEMCrypto_BufferType_Clear);
|
|
|
|
|
if (result != OEMCrypto_SUCCESS) return result;
|
|
|
|
|
if (algorithm != OEMCrypto_HMAC_SHA256) {
|
|
|
|
|
LOGE("[Generic_Sign(): bad algorithm.");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
@@ -877,27 +887,13 @@ OEMCryptoResult SessionContext::Generic_Verify(const uint8_t* in_buffer,
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
const std::vector<uint8_t>& key = current_content_key()->value();
|
|
|
|
|
const KeyControlBlock& control = current_content_key()->control();
|
|
|
|
|
if (static_cast<int>(key.size()) != SHA256_DIGEST_LENGTH) {
|
|
|
|
|
LOGE("[Generic_Verify(): CONTENT_KEY has wrong size: %d", key.size());
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
if (!(control.control_bits() & kControlAllowVerify)) {
|
|
|
|
|
LOGE("[Generic_Verify(): control bit says not allowed.");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
if (control.duration() > 0) {
|
|
|
|
|
if (control.duration() < CurrentTimer()) {
|
|
|
|
|
LOGE("[Generic_Verify(): key expired.");
|
|
|
|
|
return OEMCrypto_ERROR_KEY_EXPIRED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (control.control_bits() & kControlReplayMask) {
|
|
|
|
|
if (!IsUsageEntryValid()) {
|
|
|
|
|
LOGE("[Generic_Verify(): usage entry not valid]");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
OEMCryptoResult result = AllowKeyUse("Generic_Verify", kControlAllowVerify,
|
|
|
|
|
OEMCrypto_BufferType_Clear);
|
|
|
|
|
if (result != OEMCrypto_SUCCESS) return result;
|
|
|
|
|
if (algorithm != OEMCrypto_HMAC_SHA256) {
|
|
|
|
|
LOGE("[Generic_Verify(): bad algorithm.");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
@@ -1083,40 +1079,10 @@ OEMCryptoResult SessionContext::DecryptCENC(
|
|
|
|
|
LOGE("[DecryptCTR(): OEMCrypto_ERROR_NO_CONTENT_KEY]");
|
|
|
|
|
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
|
|
|
|
}
|
|
|
|
|
const KeyControlBlock& control = current_content_key()->control();
|
|
|
|
|
if (control.control_bits() & kControlDataPathSecure) {
|
|
|
|
|
if (!ce_->config_closed_platform() &&
|
|
|
|
|
buffer_type == OEMCrypto_BufferType_Clear) {
|
|
|
|
|
LOGE("[DecryptCTR(): Secure key with insecure buffer]");
|
|
|
|
|
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (control.duration() > 0) {
|
|
|
|
|
if (control.duration() < CurrentTimer()) {
|
|
|
|
|
LOGE("[DecryptCTR(): KEY_EXPIRED]");
|
|
|
|
|
return OEMCrypto_ERROR_KEY_EXPIRED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (control.control_bits() & kControlReplayMask) {
|
|
|
|
|
if (!IsUsageEntryValid()) {
|
|
|
|
|
LOGE("[DecryptCTR(): usage entry not valid]");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!ce_->config_local_display_only()) {
|
|
|
|
|
// Only look at HDCP if the display is non-local.
|
|
|
|
|
if (control.control_bits() & kControlHDCPRequired) {
|
|
|
|
|
uint8_t required_hdcp =
|
|
|
|
|
(control.control_bits() & kControlHDCPVersionMask) >>
|
|
|
|
|
kControlHDCPVersionShift;
|
|
|
|
|
// For reference implementation, we pretend we can handle the current
|
|
|
|
|
// HDCP version.
|
|
|
|
|
if (required_hdcp > ce_->config_current_hdcp_capability() ||
|
|
|
|
|
ce_->config_current_hdcp_capability() == 0) {
|
|
|
|
|
return OEMCrypto_ERROR_INSUFFICIENT_HDCP;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OEMCryptoResult result = AllowKeyUse("DecryptCENC", 0, buffer_type);
|
|
|
|
|
if (result != OEMCrypto_SUCCESS) return result;
|
|
|
|
|
|
|
|
|
|
const std::vector<uint8_t>& content_key = current_content_key()->value();
|
|
|
|
|
|
|
|
|
|
// Set the AES key.
|
|
|
|
|
|