OPK v17.1.1

This release fixes a flaw in the OPK code that could allow content that
requires HDCP 2 to output over a display connection that only supports
HDCP 1. This bug would only be triggered if the WTPI implementation
reports the minor version number of HDCP 1 connections. If your
implementation of WTPI_CurrentHDCPCapability() ever returns HDCP_V1_0,
HDCP_V1_1, HDCP_V1_2, HDCP_V1_3, or HDCP_V1_4, your device is vulnerable
and you should take this patch urgently. If your implementation of
WTPI_CurrentHDCPCapability() only ever returns HDCP_V1 for HDCP 1
connections or does not support HDCP 1, then your device is not
affected.

This release also fixes an incorrect version number in ODK.
This commit is contained in:
John "Juce" Bruce
2023-03-09 16:03:55 -08:00
parent 5232c51e33
commit f998d6c4ae
3 changed files with 59 additions and 2 deletions

View File

@@ -4,6 +4,7 @@
#include "oemcrypto_session.h"
#include <stdbool.h>
#include <string.h>
#include "odk.h"
@@ -1053,6 +1054,45 @@ OEMCryptoResult OPKI_GetKeyControlBlock(
return OEMCrypto_SUCCESS;
}
static bool PrioritizeHdcpLevel(OEMCrypto_HDCP_Capability level,
uint8_t* priority) {
// Since OEMCrypto_HDCP_Capability is no longer sorted, we need to convert all
// values to a sorted priority so we can efficiently compare them.
//
// If new enum values are added to OEMCrypto_HDCP_Capability, we'll have to
// add them to this function. Since OEMCrypto_HDCP_Capability is no longer
// sorted, we cannot assume we know how to handle new values.
if (level == HDCP_NONE || level == HDCP_V1 ||
level == HDCP_NO_DIGITAL_OUTPUT) {
*priority = (uint8_t)level;
return true;
} else if (level >= HDCP_V2 && level <= HDCP_V2_3) {
*priority = (uint8_t)level + 5;
return true;
} else if (level >= HDCP_V1_0 && level <= HDCP_V1_4) {
*priority = (uint8_t)level - 4;
return true;
} else {
return false;
}
}
static bool IsHdcpLevelSufficient(OEMCrypto_HDCP_Capability required,
OEMCrypto_HDCP_Capability current) {
uint8_t required_priority = 0;
if (!PrioritizeHdcpLevel(required, &required_priority)) {
LOGE("Unrecognized HDCP requirement %u", required);
return false;
}
uint8_t current_priority = 0;
if (!PrioritizeHdcpLevel(current, &current_priority)) {
LOGE("Unrecognized current HDCP level %u", current);
return false;
}
return current_priority >= required_priority;
}
OEMCryptoResult OPKI_CheckCurrentContentKeyUsage(
OEMCryptoSession* session, OEMCryptoEntitledKeySession* key_session,
uint32_t use_type, OPK_OutputBuffer_Type buffer_type) {
@@ -1096,7 +1136,8 @@ OEMCryptoResult OPKI_CheckCurrentContentKeyUsage(
const uint8_t required_hdcp =
(control.control_bits & CONTROL_HDCP_VERSION_MASK) >>
CONTROL_HDCP_VERSION_SHIFT;
if (required_hdcp > capability || capability == HDCP_NONE) {
if (!IsHdcpLevelSufficient(required_hdcp, capability) ||
capability == HDCP_NONE) {
return OEMCrypto_ERROR_INSUFFICIENT_HDCP;
}
}