window显示驱动开发—可选内容保护 DDI 函数

发布于:2025-08-05 ⋅ 阅读:(14) ⋅ 点赞:(0)

驱动程序可以选择性地支持以下内容保护 DDI 函数:

  • EncryptionBlt 函数从受保护的图面读取加密数据。
  • GetPitch 函数检索受保护图面的间距。
  • StartSessionKeyRefresh 函数返回一个随机数,解码器/应用程序和驱动程序/硬件随后可以使用该随机数执行独占 OR 操作, (XOR) 会话密钥。
  • FinishSessionKeyRefresh 函数指示来自该时间点的所有缓冲区都将使用更新的会话键值。
  • GetEncryptionBltKey 函数返回用于解密驱动程序的 EncryptionBlt 函数返回的数据的密钥。
  • DecryptionBlt 函数将数据写入受保护的图面。

1. EncryptionBlt - 受保护图面数据读取

1.1 函数原型

HRESULT APIENTRY EncryptionBlt(
    D3DDDIARG_ENCRYPTIONBLT* pEncryptBlt);

1.2 实现要点

HRESULT APIENTRY EncryptionBlt(D3DDDIARG_ENCRYPTIONBLT* pEncryptBlt)
{
    // 验证输入参数
    if (!pEncryptBlt->hSrcResource || !pEncryptBlt->pEncryptedBlock)
        return E_INVALIDARG;

    // 检查资源保护状态
    if (!IsResourceProtected(pEncryptBlt->hSrcResource))
        return D3DDDIERR_INVALIDPROTECT;

    // 获取加密密钥句柄
    HCRYPTKEY hKey = GetCurrentSessionKey();

    // 使用硬件加密引擎
    if (FAILED(HW_EncryptSurface(
            pEncryptBlt->hSrcResource,
            pEncryptBlt->pEncryptedBlock,
            pEncryptBlt->EncryptedBlockSize,
            hKey))) {
        return E_FAIL;
    }

    return S_OK;
}

安全要求:

必须验证源资源具有D3DUSAGE_PROTECTED标志

加密操作应在安全执行环境(TEE)中完成

输出数据必须使用会话密钥加密

2. GetPitch - 获取受保护图面间距

2.1 典型实现

HRESULT APIENTRY GetPitch(
    D3DDDIARG_GETPITCH* pGetPitch)
{
    RESOURCE_CTX* pResCtx = (RESOURCE_CTX*)pGetPitch->hResource;
    
    // 保护资源需要特殊对齐
    if (pResCtx->Flags.Protected) {
        pGetPitch->Pitch = ALIGN_UP(pResCtx->Width, 64);
    } else {
        pGetPitch->Pitch = pResCtx->Pitch;
    }
    
    return S_OK;
}

注意事项:

  • 保护图面通常需要64字节或128字节对齐
  • 间距值应匹配硬件加密引擎要求

3. 会话密钥刷新机制

3.1 StartSessionKeyRefresh

HRESULT APIENTRY StartSessionKeyRefresh(
    D3DDDIARG_STARTSESSIONKEYREFRESH* pKeyRefresh)
{
    CRYPTO_SESSION_CTX* pSession = 
        (CRYPTO_SESSION_CTX*)pKeyRefresh->hCryptoSession;
    
    // 生成安全随机数
    BCryptGenRandom(
        NULL,
        pKeyRefresh->pRandomNumber,
        pKeyRefresh->RandomNumberSize,
        BCRYPT_USE_SYSTEM_PREFERRED_RNG);
    
    // 保存原始密钥用于过渡期
    pSession->PendingKeyRefresh = TRUE;
    memcpy(pSession->OldKey, pSession->CurrentKey, KEY_SIZE);
    
    return S_OK;
}

3.2 FinishSessionKeyRefresh

HRESULT APIENTRY FinishSessionKeyRefresh(
    D3DDDIARG_FINISHSESSIONKEYREFRESH* pKeyRefresh)
{
    CRYPTO_SESSION_CTX* pSession = 
        (CRYPTO_SESSION_CTX*)pKeyRefresh->hCryptoSession;
    
    if (!pSession->PendingKeyRefresh)
        return D3DDDIERR_INVALIDCALL;
    
    // 应用新密钥
    XOR_Keys(pSession->CurrentKey, pKeyRefresh->pXORKey);
    
    // 清除过渡状态
    pSession->PendingKeyRefresh = FALSE;
    SecureZeroMemory(pSession->OldKey, KEY_SIZE);
    
    return S_OK;
}

密钥刷新流程:

4. GetEncryptionBltKey - 获取解密密钥

4.1 安全实现

HRESULT APIENTRY GetEncryptionBltKey(
    D3DDDIARG_GETENCRYPTIONBLTKEY* pKeyData)
{
    if (!pKeyData->hCryptoSession)
        return E_INVALIDARG;
    
    CRYPTO_SESSION_CTX* pSession = 
        (CRYPTO_SESSION_CTX*)pKeyData->hCryptoSession;
    
    // 密钥必须加密传输
    if (FAILED(EncryptKeyForTransport(
            pSession->CurrentKey,
            pKeyData->pKey,
            pKeyData->KeySize))) {
        return E_FAIL;
    }
    
    return S_OK;
}

保护措施:

  • 使用接收方公钥加密传输密钥
  • 限制密钥有效时间(通常<2秒)

5. DecryptionBlt - 受保护图面写入

5.1 完整实现

HRESULT APIENTRY DecryptionBlt(
    D3DDDIARG_DECRYPTIONBLT* pDecryptBlt)
{
    // 参数验证
    if (!pDecryptBlt->hDstResource || !pDecryptBlt->pEncryptedBlock)
        return E_INVALIDARG;
    
    // 检查目标保护状态
    if (!IsResourceProtected(pDecryptBlt->hDstResource))
        return D3DDDIERR_INVALIDPROTECT;
    
    // 获取当前会话密钥
    HCRYPTKEY hKey = GetCurrentSessionKey();
    
    // 硬件解密操作
    if (FAILED(HW_DecryptToSurface(
            pDecryptBlt->pEncryptedBlock,
            pDecryptBlt->EncryptedBlockSize,
            pDecryptBlt->hDstResource,
            hKey))) {
        return E_FAIL;
    }
    
    return S_OK;
}

6. 安全架构设计

6.1 密钥生命周期管理

stateDiagram-v2
    [*] --> KeyGen: CreateCryptoSession
    KeyGen --> Active: 正常使用
    Active --> Refreshing: StartRefresh
    Refreshing --> Active: FinishRefresh
    Active --> Revoked: 检测到攻击
    Revoked --> [*]

6.2 内存保护机制

typedef struct _PROTECTED_RESOURCE {
    D3DKMT_HANDLE hAllocation;
    BOOL IsEncrypted;
    PHYSICAL_ADDRESS SecurePA; // 受保护物理地址
    CRYPTO_KEY_HANDLE hKey;    // 关联密钥
} PROTECTED_RESOURCE;

7. 性能优化技巧

批量加密操作:

void OptimizedEncryptionBlt()
{
    if (SupportsBulkEncrypt()) {
        HW_BulkEncrypt(/* 多个表面 */);
    } else {
        // 回退到单表面处理
    }
}

密钥缓存:

class KeyCache {
public:
    void CacheKey(HCRYPTOKEY hKey, const BYTE* pKeyData) {
        m_cache[hKey] = SecureDuplicateKey(pKeyData);
    }
private:
    std::map<HCRYPTOKEY, SecureKey> m_cache;
};

8. 认证测试要求

WHQL测试项目:

  • 强制密钥刷新测试
  • 加密/解密往返验证
  • 无效句柄测试

抗攻击测试:

# 伪代码:模拟中间人攻击
def test_key_refresh_attack():
    orig_key = get_key()
    start_refresh()
    inject_fake_key()
    assert system_rejects_finish()

9. 错误处理规范

错误码 描述
D3DDDIERR_INVALIDPROTECT 资源保护状态不匹配
D3DDDIERR_KEYEDTOOMANY 密钥使用次数超限
E_CRYPTO_NOT_INIT 加密引擎未初始化

 


网站公告

今日签到

点亮在社区的每一天
去签到