lineage_kernel_xcoverpro/drivers/soc/samsung/exynos-hdcp/exynos-hdcp2-protocol-msg.c

1071 lines
26 KiB
C
Executable File

/*
* drivers/soc/samsung/exynos-hdcp/exynos-hdcp2-protocol-msg.c
*
* Copyright (c) 2016 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include "exynos-hdcp2-config.h"
#include "exynos-hdcp2-protocol-msg.h"
#include "exynos-hdcp2-teeif.h"
#include "exynos-hdcp2.h"
#include "exynos-hdcp2-log.h"
#include "exynos-hdcp2-misc.h"
#include "dp_link/exynos-hdcp2-dplink-protocol-msg.h"
/* HDCP protocol message capulate & decapulate functions for IIA */
static int cap_ake_init(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int cap_ake_transmitter_info(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int cap_ake_no_stored_km(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int cap_ake_stored_km(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int decap_ake_send_cert(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int decap_ake_receiver_info(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int decap_ake_send_rrx(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int decap_ake_send_h_prime(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int decap_ake_send_pairing_info(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int cap_lc_init(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int cap_rtt_challenge(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int decap_lc_send_l_prime(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int decap_rtt_ready(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int cap_ske_send_eks(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int decap_RepeaterAuth_send_ReceiverID_List(uint8_t *m,size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int cap_RepeaterAuth_Send_Ack(uint8_t *m,size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int decap_Receiver_AuthStatus(uint8_t *m,size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int cap_RepeaterAuth_Stream_Manage(uint8_t *m,size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
static int decap_RepeaterAuth_Stream_Ready(uint8_t *m,size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx);
int (*proto_iia[])(uint8_t *, size_t *,
struct hdcp_tx_ctx *,
struct hdcp_rx_ctx *) = {
cap_ake_init,
decap_ake_send_cert,
cap_ake_no_stored_km,
cap_ake_stored_km,
decap_ake_send_rrx,
decap_ake_send_h_prime,
decap_ake_send_pairing_info,
cap_lc_init,
decap_lc_send_l_prime,
cap_ske_send_eks,
decap_RepeaterAuth_send_ReceiverID_List,
decap_rtt_ready,
cap_rtt_challenge,
cap_RepeaterAuth_Send_Ack,
cap_RepeaterAuth_Stream_Manage,
decap_RepeaterAuth_Stream_Ready,
decap_Receiver_AuthStatus,
cap_ake_transmitter_info,
decap_ake_receiver_info,
};
/* HDCP protocol message capulate & decapulate functions for DP_LINK */
extern int (*proto_dp[])(uint8_t *, size_t *,
struct hdcp_tx_ctx *,
struct hdcp_rx_ctx *);
int ske_generate_sessionkey(uint32_t lk_type, uint8_t *enc_skey, int share_skey)
{
int ret;
ret = teei_generate_skey(lk_type,
enc_skey, HDCP_SKE_SKEY_LEN,
share_skey);
if (ret) {
hdcp_err("generate_session_key() is failed with %x\n", ret);
return ERR_GENERATE_SESSION_KEY;
}
return 0;
}
int ske_generate_riv(uint8_t *out)
{
int ret;
ret = teei_generate_riv(out, HDCP_RTX_BYTE_LEN);
if (ret) {
hdcp_err("teei_generate_riv() is failed with %x\n", ret);
return ERR_GENERATE_NON_SECKEY;
}
return 0;
}
int lc_generate_rn(uint8_t *out, size_t out_len)
{
int ret;
ret = teei_gen_rn(out, out_len);
if (ret) {
hdcp_err("lc_generate_rn() is failed with %x\n", ret);
return ERR_GENERATE_NON_SECKEY;
}
return 0;
}
int lc_make_hmac(struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx, uint32_t lk_type)
{
int ret;
if ((rx_ctx->version != HDCP_VERSION_2_0) &&
tx_ctx->lc_precomp && rx_ctx->lc_precomp) {
ret = teei_gen_lc_hmac(lk_type,
tx_ctx->lsb16_hmac);
if (ret) {
hdcp_err("compute_lc_whmac() is failed with %x\n", ret);
return ERR_COMPUTE_LC_HMAC;
}
} else {
hdcp_err("LC precomp is not supported\n");
return ERR_COMPUTE_LC_HMAC;
}
return ret;
}
int lc_compare_hmac(uint8_t *rx_hmac, size_t hmac_len)
{
int ret;
ret = teei_compare_lc_hmac(rx_hmac, hmac_len);
if (ret) {
hdcp_err("compare_lc_hmac_val() is failed with %x\n", ret);
return ERR_COMPARE_LC_HMAC;
}
return ret;
}
static int ake_generate_rtx(uint32_t lk_type, uint8_t *out, size_t out_len)
{
int ret;
/* IIA Spec does not use TxCaps */
ret = teei_gen_rtx(lk_type, out, out_len, NULL, 0);
if (ret) {
hdcp_err("generate rtx is failed with 0x%x\n", ret);
return ERR_GENERATE_NON_SECKEY;
}
return 0;
}
static int ake_set_tx_info(struct hdcp_tx_ctx *tx_ctx)
{
int ret;
uint8_t version[HDCP_VERSION_LEN];
uint8_t caps_mask[HDCP_CAPABILITY_MASK_LEN];
/* Init Version & Precomputation */
ret = teei_get_txinfo(version, HDCP_VERSION_LEN,
caps_mask, HDCP_CAPABILITY_MASK_LEN);
if (ret) {
hdcp_err("Get Tx info is failed with 0x%x\n", ret);
return ERR_GET_TX_INFO;
}
hdcp_debug("Tx: version(0x%02x) Caps_maks(0x%02x%02x)\n",
version[0], caps_mask[0], caps_mask[1]);
tx_ctx->version = version[0];
tx_ctx->lc_precomp = caps_mask[1];
/* todo: check seq_num_M init position*/
tx_ctx->seq_num_M = 0;
return 0;
}
static int ake_set_rx_info(struct hdcp_rx_ctx *rx_ctx)
{
int ret;
uint8_t version[HDCP_VERSION_LEN];
uint8_t caps_mask[HDCP_CAPABILITY_MASK_LEN];
version[0] = rx_ctx->version;
caps_mask[0] = 0x00; /* reserved field in IIA spec */
caps_mask[1] = rx_ctx->lc_precomp;
/* Init Version & Precomputation */
ret = teei_set_rxinfo(version, HDCP_VERSION_LEN,
caps_mask, HDCP_CAPABILITY_MASK_LEN);
if (ret) {
hdcp_err("Get Tx info is failed with 0x%x\n", ret);
return ERR_SET_RX_INFO;
}
return 0;
}
static int ake_set_rrx(uint8_t *rrx, size_t rrx_len)
{
int ret;
/* set Rrx value */
ret = teei_set_rrx(rrx, rrx_len);
if (ret) {
hdcp_err("set rrx is failed with 0x%x\n", ret);
return ERR_SET_RRX;
}
return 0;
}
int ake_verify_cert(uint8_t *cert, size_t cert_len,
uint8_t *rrx, size_t rrx_len,
uint8_t *rx_caps, size_t rx_caps_len)
{
int ret;
ret = teei_verify_cert(cert, cert_len,
rrx, rrx_len,
rx_caps, rx_caps_len);
if (ret) {
hdcp_err("teei_verify_cert() is failed with %x\n", ret);
return ERR_VERIFY_CERT;
}
return 0;
}
int ake_generate_masterkey(uint32_t lk_type, uint8_t *enc_mkey, size_t elen)
{
int ret;
/* Generate Encrypted & Wrapped Master Key */
ret = teei_generate_master_key(lk_type, enc_mkey, elen);
if (ret) {
hdcp_err("generate_master_key() is failed with %x\n", ret);
return ERR_GENERATE_MASTERKEY;
}
return ret;
}
int ake_compare_hmac(uint8_t *rx_hmac, size_t rx_hmac_len)
{
int ret;
ret = teei_compare_ake_hmac(rx_hmac, rx_hmac_len);
if (ret) {
hdcp_err("teei_compare_hmac() is failed with %x\n", ret);
return ERR_COMPUTE_AKE_HMAC;
}
return 0;
}
int ake_store_master_key(uint8_t *ekh_mkey, size_t ekh_mkey_len)
{
int ret;
ret = teei_set_pairing_info(ekh_mkey, ekh_mkey_len);
if (ret) {
hdcp_err("teei_store_pairing_info() is failed with %x\n", ret);
return ERR_STORE_MASTERKEY;
}
return 0;
}
int ake_find_masterkey(int *found_km,
uint8_t *ekh_mkey, size_t ekh_mkey_len,
uint8_t *m, size_t m_len)
{
int ret;
ret = teei_get_pairing_info(ekh_mkey, ekh_mkey_len, m, m_len);
if (ret) {
if (ret == E_HDCP_PRO_INVALID_RCV_ID) {
hdcp_info("RCV id is not found\n");
*found_km = 0;
return 0;
} else {
*found_km = 0;
hdcp_err("teei_store_pairing_info() is failed with %x\n", ret);
return ERR_FIND_MASTERKEY;
}
}
*found_km = 1;
return 0;
}
static int cap_ake_init(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
size_t rtx_len;
int ret;
/* Buffer Check */
if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL))
return ERR_WRONG_BUFFER;
rtx_len = HDCP_AKE_RTX_BYTE_LEN;
/* Generate rtx */
ret = ake_generate_rtx(HDCP_LINK_TYPE_IIA, tx_ctx->rtx, rtx_len);
if (ret) {
hdcp_err("failed to generate rtx\n");
return ERR_GENERATE_RTX;
}
/* Make Message */
m[0] = AKE_INIT;
memcpy(&m[1], tx_ctx->rtx, rtx_len);
*m_len = 1 + rtx_len;
#ifdef HDCP_AKE_DEBUG
hdcp_debug("HDCP: cap_ake_init(%lu) \n", *m_len);
hdcp_hexdump(m, *m_len);
#endif
return 0;
}
static int cap_ake_transmitter_info(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret;
if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL))
return ERR_WRONG_BUFFER;
/* Set info */
ret = ake_set_tx_info(tx_ctx);
if (ret) {
hdcp_err("failed to set info\n");
return ERR_SET_INFO;
}
/* Make Message */
m[0] = AKE_TRANSMITTER_INFO;
m[1] = 0x0;
m[2] = 0x06;
m[3] = tx_ctx->version;
m[4] = 0x0;
m[5] = tx_ctx->lc_precomp;
*m_len = 6;
#ifdef HDCP_AKE_DEBUG
hdcp_debug("cap_ake_transmitter_info(%lu) \n", *m_len);
hdcp_hexdump(m, *m_len);
#endif
return 0;
}
static int cap_ake_no_stored_km(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
uint8_t enc_mkey[HDCP_AKE_ENCKEY_BYTE_LEN];
int ret;
if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL) ||
(rx_ctx == NULL))
return ERR_WRONG_BUFFER;
/* Verify Certificate */
/* IIA spec does not define rrx and RxCaps with Cert message */
ret = ake_verify_cert(rx_ctx->cert, sizeof(rx_ctx->cert),
NULL, 0,
&(rx_ctx->repeater), HDCP_RX_CAPS_LEN);
if (ret)
/* authentication failure &
* aborts the authentication protocol */
return ret;
/* Generate/Encrypt master key */
ret = ake_generate_masterkey(HDCP_LINK_TYPE_IIA,
enc_mkey, sizeof(enc_mkey));
/* Generate/Encrypt master key */
if (ret)
return ret;
/* Make Message */
m[0] = AKE_NO_STORED_KM;
memcpy(&m[1], enc_mkey, HDCP_AKE_ENCKEY_BYTE_LEN);
*m_len = 1 + HDCP_AKE_ENCKEY_BYTE_LEN;
#ifdef HDCP_AKE_DEBUG
hdcp_debug("cap_ake_no_stored_km(%lu)\n", *m_len);
hdcp_hexdump(m, *m_len);
#endif
return 0;
}
static int cap_ake_stored_km(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret;
int found_km;
if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL))
return ERR_WRONG_BUFFER;
/* Generate/Encrypt master key */
ret = ake_find_masterkey(&found_km,
tx_ctx->ekh_mkey, HDCP_AKE_EKH_MKEY_BYTE_LEN,
tx_ctx->m, HDCP_AKE_M_BYTE_LEN);
if (ret || !found_km) {
hdcp_err("find_masterkey() is failed with 0x%x\n", ret);
return -1;
}
/* Make Message */
m[0] = AKE_STORED_KM;
memcpy(&m[1], tx_ctx->ekh_mkey, HDCP_AKE_EKH_MKEY_BYTE_LEN);
memcpy(&m[1] + HDCP_AKE_EKH_MKEY_BYTE_LEN, tx_ctx->m, HDCP_AKE_M_BYTE_LEN);
*m_len = 1 + HDCP_AKE_EKH_MKEY_BYTE_LEN + HDCP_AKE_M_BYTE_LEN;
#ifdef HDCP_AKE_DEBUG
hdcp_debug("cap_ake_stored_km(%lu) \n", *m_len);
hdcp_hexdump(m, *m_len);
#endif
return 0;
}
static int decap_ake_send_cert(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret;
ret = check_received_msg(m, *m_len, 2 + HDCP_RX_CERT_LEN, AKE_SEND_CERT);
if (ret)
return ret;
rx_ctx->repeater = m[1];
memcpy(rx_ctx->cert, &m[2], HDCP_RX_CERT_LEN);
#ifdef HDCP_AKE_DEBUG
hdcp_debug("decap_ake_send_cert(%lu) \n", *m_len);
hdcp_hexdump(m, *m_len);
#endif
return 0;
}
static int decap_ake_receiver_info(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret;
ret = check_received_msg(m, *m_len, 6, AKE_RECEIVER_INFO);
if (ret)
return ret;
if ((m[2] < 6) && (m[1] == 0)) {
hdcp_err("AKE_Receiver_Info, send wrong length\n");
return ERR_WRONG_MESSAGE_LENGTH;
}
rx_ctx->version = m[3];
rx_ctx->lc_precomp = m[5];
ret = ake_set_rx_info(rx_ctx);
if (ret) {
hdcp_err("AKE set rx info failed. ret(0x%x)\n", ret);
return ret;
}
#ifdef HDCP_AKE_DEBUG
hdcp_debug("decap_ake_receiver_info()\n");
hdcp_debug("version: 0x%02x\n", rx_ctx->version);
hdcp_debug("HDCP lc_precomp: 0x%02x\n", rx_ctx->lc_precomp);
#endif
return 0;
}
static int decap_ake_send_rrx(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret;
uint8_t rrx[HDCP_RRX_BYTE_LEN] = {0};
ret = check_received_msg(m, *m_len, 1 + HDCP_RRX_BYTE_LEN, AKE_SEND_RRX);
if (ret)
return ret;
memcpy(rx_ctx->rrx, &m[1], HDCP_RRX_BYTE_LEN);
memcpy(rrx, &m[1], HDCP_RRX_BYTE_LEN);
ret = ake_set_rrx(rrx, HDCP_RRX_BYTE_LEN);
if (ret)
return ret;
#ifdef HDCP_AKE_DEBUG
hdcp_debug("decap_ake_send_rrx\n");
hdcp_hexdump(rx_ctx->rrx, HDCP_RRX_BYTE_LEN);
#endif
return 0;
}
static int decap_ake_send_h_prime(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret;
ret = check_received_msg(m, *m_len, 1 + HDCP_HMAC_SHA256_LEN,
AKE_SEND_H_PRIME);
if (ret)
return ret;
/* compare H == H' */
ret = ake_compare_hmac(&m[1], HDCP_HMAC_SHA256_LEN);
if (ret)
return ret;
#ifdef HDCP_AKE_DEBUG
hdcp_debug("decap_ake_send_h_prime\n");
hdcp_debug("given hmac:\n");
hdcp_hexdump(&m[1], HDCP_HMAC_SHA256_LEN);
#endif
return 0;
}
static int decap_ake_send_pairing_info(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret;
ret = check_received_msg(m, *m_len, 1 + HDCP_AKE_EKH_MKEY_BYTE_LEN,
AKE_SEND_PAIRING_INFO);
if (ret)
return ret;
memcpy(tx_ctx->ekh_mkey, &m[1], HDCP_AKE_EKH_MKEY_BYTE_LEN);
/* Store the Key */
ret = ake_store_master_key(tx_ctx->ekh_mkey, HDCP_AKE_EKH_MKEY_BYTE_LEN);
if (ret)
return ret;
#ifdef HDCP_AKE_DEBUG
hdcp_debug("decap_ake_send_pairing_info(%lu)\n", *m_len);
hdcp_debug("rx_ctx->ekh_mkey:\n");
hdcp_hexdump(tx_ctx->ekh_mkey, HDCP_AKE_MKEY_BYTE_LEN);
#endif
return 0;
}
static int cap_lc_init(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret;
if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL) || (rx_ctx ==
NULL))
return ERR_WRONG_BUFFER;
/* Generate rn */
ret = lc_generate_rn(tx_ctx->rn, HDCP_RTX_BYTE_LEN);
if (ret) {
hdcp_err("failed to generate rtx\n");
return ERR_GENERATE_RN;
}
/* Make Message */
m[0] = LC_INIT;
memcpy(&m[1], tx_ctx->rn, HDCP_RTX_BYTE_LEN);
*m_len = 1 + HDCP_RTX_BYTE_LEN;
if ((rx_ctx->version != HDCP_VERSION_2_0) &&
tx_ctx->lc_precomp &&
rx_ctx->lc_precomp) {
/* compute HMAC,
* return the least significant 128-bits,
* the most significant 128-bits wrapped */
ret = lc_make_hmac(tx_ctx, rx_ctx, 0); // last param 0 have to be checked, PKY
if (ret)
return ret;
}
#ifdef HDCP_LC_DEBUG
hdcp_debug("LC_Init(%u)\n", *m_len);
hdcp_hexdump(m, *m_len);
#endif
return 0;
}
static int cap_rtt_challenge(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL))
return ERR_WRONG_BUFFER;
/* Make Message */
m[0] = RTT_CHALLENGE;
memcpy(&m[1], tx_ctx->lsb16_hmac, HDCP_HMAC_SHA256_LEN / 2);
*m_len = 1 + (HDCP_HMAC_SHA256_LEN / 2);
#ifdef HDCP_LC_DEBUG
hdcp_debug("RTT_Challenge(%lu)\n", *m_len);
hdcp_hexdump(m, *m_lne);
#endif
return 0;
}
static int decap_lc_send_l_prime(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
uint8_t *rx_hmac;
size_t len;
int ret;
/* find length depending precomputation */
if ((rx_ctx->version == HDCP_VERSION_2_0) || !tx_ctx->lc_precomp ||
!rx_ctx->lc_precomp)
len = HDCP_HMAC_SHA256_LEN;
else
len = HDCP_HMAC_SHA256_LEN/2;
ret = check_received_msg(m, *m_len, 1 + len, LC_SEND_L_PRIME);
if (ret)
return ret;
/* No_precomputation: compare hmac
precomputation: compare the most significant 128bits of L & L' */
rx_hmac = &m[1];
ret = lc_compare_hmac(rx_hmac, len);
if (ret)
return ret;
#ifdef HDCP_LC_DEBUG
hdcp_debug("LC_Send_L_prime\n");
hdcp_debug("rx_hmac:\n");
hdcp_hexdump(rx_hmac, len);
#endif
return 0;
}
static int decap_rtt_ready(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret;
ret = check_received_msg(m, *m_len, 1, RTT_READY);
if (ret)
return ret;
#ifdef HDCP_LC_DEBUG
hdcp_debug("RTT_Ready\n");
#endif
return 0;
}
static int cap_ske_send_eks(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret;
uint8_t enc_skey[HDCP_AKE_MKEY_BYTE_LEN];
if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL) ||
(rx_ctx == NULL))
return ERR_WRONG_BUFFER;
/* Generate riv */
if (!tx_ctx->share_skey) {
ret = ske_generate_riv(tx_ctx->riv);
if (ret)
return ERR_GENERATE_RIV;
}
/* Generate encrypted Session Key */
ret = ske_generate_sessionkey(0, enc_skey, tx_ctx->share_skey);
if (ret)
return ret;
/* Make Message */
m[0] = SKE_SEND_EKS;
memcpy(&m[1], enc_skey, HDCP_AKE_MKEY_BYTE_LEN);
memcpy(&m[1 + HDCP_AKE_MKEY_BYTE_LEN], tx_ctx->riv, HDCP_RTX_BYTE_LEN);
*m_len = 1 + HDCP_AKE_MKEY_BYTE_LEN + HDCP_RTX_BYTE_LEN;
#ifdef HDCP_SKE_DEBUG
hdcp_debug("SKE_Send_Eks(%lu)\n", *m_len);
hdcp_hexdump(m, *m_len);
#endif
return 0;
}
#ifdef TEST_HDCP_V2_0
int parse_rcvid_list(uint8_t *msg, struct hdcp_tx_ctx *tx_ctx)
{
/* get PRE META values */
tx_ctx->rcv_list.devs_exd = (uint8_t)*msg;
tx_ctx->rcv_list.cascade_exd = (uint8_t)*(msg + 1);
/* get META values */
msg += HDCP_RP_RCV_LIST_PRE_META_LEN;
tx_ctx->rcv_list.devs_count = (uint8_t)*msg;
tx_ctx->rcv_list.depth = (uint8_t)*(msg + 1);
memcpy(tx_ctx->rcv_list.hmac_prime, (uint8_t *)(msg + 2), 32);
/* get receiver ID list */
msg += 34;
memcpy(tx_ctx->rcv_list.rcv_id, msg, tx_ctx->rcv_list.devs_count * HDCP_RCV_ID_LEN);
return 0;
}
void convert_rcvlist2authmsg(struct hdcp_rcvlist *rcv_list, uint8_t *src_msg, size_t *msg_len)
{
int i;
*msg_len = 0;
for (i = 0; i < rcv_list->devs_count; i++) {
memcpy(src_msg + *msg_len, rcv_list->rcv_id[i], HDCP_RCV_ID_LEN);
*msg_len += HDCP_RCV_ID_LEN;
}
/* concatinate DEPTH */
memcpy(src_msg + *msg_len, &rcv_list->depth, 1);
*msg_len += 1;
/* concatinate DEVICE COUNT */
memcpy(src_msg + *msg_len, &rcv_list->devs_count, 1);
*msg_len += 1;
/* concatinate MAX DEVS EXCEEDED */
memcpy(src_msg + *msg_len, &rcv_list->devs_exd, 1);
*msg_len += 1;
/* concatinate MAX CASCADE EXCEEDED */
memcpy(src_msg + *msg_len, &rcv_list->cascade_exd, 1);
*msg_len += 1;
}
#else
int parse_rcvid_list(uint8_t *msg, struct hdcp_tx_ctx *tx_ctx)
{
/* get PRE META values */
tx_ctx->rpauth_info.devs_exd = (uint8_t)*msg;
tx_ctx->rpauth_info.cascade_exd = (uint8_t)*(msg + 1);
/* get META values */
msg += HDCP_RP_RCV_LIST_PRE_META_LEN;
tx_ctx->rpauth_info.devs_count = (uint8_t)*msg;
tx_ctx->rpauth_info.depth = (uint8_t)*(msg + 1);
tx_ctx->rpauth_info.hdcp2_down = (uint8_t)*(msg + 2);
tx_ctx->rpauth_info.hdcp1_down = (uint8_t)*(msg + 3);
memcpy(tx_ctx->rpauth_info.seq_num_v, (uint8_t *)(msg + 4), 3);
memcpy(tx_ctx->rpauth_info.v_prime, (uint8_t *)(msg + 7), 16);
/* get receiver ID list */
msg += HDCP_RP_RCV_LIST_META_LEN;
if (tx_ctx->rpauth_info.devs_count > HDCP_RCV_DEVS_COUNT_MAX) {
hdcp_err("invalid DEVS count (%d)\n", tx_ctx->rpauth_info.devs_count);
return -1;
}
memcpy(tx_ctx->rpauth_info.u_rcvid.arr, msg, tx_ctx->rpauth_info.devs_count * HDCP_RCV_ID_LEN);
return 0;
}
void convert_rcvlist2authmsg(struct hdcp_rpauth_info *rpauth_info, uint8_t *src_msg, size_t *msg_len)
{
int i;
*msg_len = 0;
for (i = 0; i < rpauth_info->devs_count; i++) {
memcpy(src_msg + *msg_len, rpauth_info->u_rcvid.arr[i], HDCP_RCV_ID_LEN);
*msg_len += HDCP_RCV_ID_LEN;
}
/* concatinate DEPTH */
memcpy(src_msg + *msg_len, &rpauth_info->depth, 1);
*msg_len += 1;
/* concatinate DEVICE COUNT */
memcpy(src_msg + *msg_len, &rpauth_info->devs_count, 1);
*msg_len += 1;
/* concatinate MAX DEVS EXCEEDED */
memcpy(src_msg + *msg_len, &rpauth_info->devs_exd, 1);
*msg_len += 1;
/* concatinate MAX CASCADE EXCEEDED */
memcpy(src_msg + *msg_len, &rpauth_info->cascade_exd, 1);
*msg_len += 1;
/* concatinate HDCP2 REPEATER DOWNSTREAM */
memcpy(src_msg + *msg_len, &rpauth_info->hdcp2_down, 1);
*msg_len += 1;
/* concatinate HDCP1 DEVICE DOWNSTREAM */
memcpy(src_msg + *msg_len, &rpauth_info->hdcp1_down, 1);
*msg_len += 1;
/* concatinate seq_num_v */
memcpy(src_msg + *msg_len, &rpauth_info->seq_num_v, 3);
*msg_len += 3;
}
#endif
static int decap_RepeaterAuth_send_ReceiverID_List(uint8_t *m,
size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
size_t hmac_prime_len;
size_t msg_len;
uint8_t source_msg[256];
int ret;
if (rx_ctx->version == HDCP_VERSION_2_0)
hmac_prime_len = HDCP_HMAC_SHA256_LEN;
else
hmac_prime_len = HDCP_HMAC_SHA256_LEN/2;
ret = check_received_msg(m, *m_len, 0, REPEATERAUTH_SEND_RECEIVERID_LIST);
if (ret)
return ret;
if (parse_rcvid_list(m + 1, tx_ctx))
return -1;
convert_rcvlist2authmsg(&tx_ctx->rpauth_info, source_msg, &msg_len);
ret = teei_set_rcvlist_info(NULL, NULL, tx_ctx->rpauth_info.v_prime,
source_msg, tx_ctx->rpauth_info.v, &(tx_ctx->rpauth_info.valid));
tx_ctx->rpauth_info.valid = 0;
if (ret) {
tx_ctx->rpauth_info.valid = 1;
return ret;
}
#ifdef HDCP_TX_REPEATER_DEBUG
hdcp_debug("decap_RepeaterAuth_send_ReceiverID_List valid (%u)\n", tx_ctx->rpauth_info.valid);
hdcp_hexdump(tx_ctx->rpauth_info.v, HDCP_RP_HMAC_V_LEN / 2);
#endif
return 0;
}
static int cap_RepeaterAuth_Send_Ack(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL))
return ERR_WRONG_BUFFER;
/* Make Message */
m[0] = REPEATERAUTH_SEND_ACK;
if(tx_ctx->rpauth_info.valid == 0)
memcpy(&m[1], tx_ctx->rpauth_info.v, HDCP_RP_HMAC_V_LEN / 2);
else
return ERR_SEND_ACK;
*m_len = 1 + (HDCP_RP_HMAC_V_LEN / 2);
#ifdef HDCP_TX_REPEATER_DEBUG
hdcp_debug("make_RepeaterAuth_Send_Ack(%u)\n", *m_len);
hdcp_hexdump(m, *m_len);
#endif
return 0;
}
static int decap_Receiver_AuthStatus(uint8_t *m,
size_t *m_len, struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret;
ret = check_received_msg(m, (int)*m_len, 0, RECEIVER_AUTHSTATUS);
if (ret)
return ret;
tx_ctx->rp_reauth = m[3];
#ifdef HDCP_TX_REPEATER_DEBUG
hdcp_debug("get_Receiver_AuthStatus(%u)\n", *m_len);
hdcp_debug("receiver reauth req: %u\n", tx_ctx->rp_reauth);
#endif
return 0;
}
int cap_RepeaterAuth_Stream_Manage(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int i;
uint8_t *dst;
uint16_t stmp;
uint32_t itmp;
if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL))
return ERR_WRONG_BUFFER;
if (tx_ctx->stream_ctrl.str_num > HDCP_TX_REPEATER_MAX_STREAM)
return ERR_EXCEED_MAX_STREAM;
/* Make Message */
m[0] = REPEATERAUTH_STREAM_MANAGE;
itmp = htonl(tx_ctx->seq_num_M);
memcpy(&m[1], (uint8_t *)&itmp + 1, 3);
stmp = htons(tx_ctx->stream_ctrl.str_num);
memcpy(&m[4], &stmp, sizeof(stmp));
for (i = 0; i < tx_ctx->stream_ctrl.str_num; i++) {
dst = (uint8_t *)(&m[6] + STREAM_INFO_SIZE * i);
itmp = htonl(tx_ctx->stream_ctrl.str_info[i].ctr);
memcpy(dst, &itmp, sizeof(itmp));
stmp = htons(tx_ctx->stream_ctrl.str_info[i].pid);
memcpy(dst + sizeof(itmp), &stmp, sizeof(stmp));
dst[STREAM_INFO_SIZE - 1] = tx_ctx->stream_ctrl.str_info[i].type;
}
*m_len = HDCP_PROTO_MSG_ID_LEN + STREAM_ELEM_SIZE + STREAM_INFO_SIZE * i;
/* seq_num_M++ */
tx_ctx->seq_num_M++;
/* save message to make M */
memcpy(tx_ctx->strmsg, &m[6], *m_len - 6);
memcpy(tx_ctx->strmsg + *m_len - 6, &m[1], 3);
tx_ctx->strmsg_len = *m_len - 3;
#ifdef HDCP_TX_REPEATER_DEBUG
hdcp_debug("strmsg(len: %d): \n", tx_ctx->strmsg_len);
hdcp_hexdump(tx_ctx->strmsg, tx_ctx->strmsg_len);
hdcp_debug("message(len: %d): \n", *m_len);
hdcp_hexdump(m, *m_len);
hdcp_debug("seq_num_M: %d\n", tx_ctx->seq_num_M);
#endif
return 0;
}
int decap_RepeaterAuth_Stream_Ready(uint8_t *m, size_t *m_len,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret = 0;
/* Not support yet*/
#if 0
ret = check_received_msg(m, *m_len, 1 + HDCP_HMAC_SHA256_LEN, REPEATERAUTH_STREAM_READY);
if (ret)
return ret;
/* compute M and compare M == M' */
ret = teei_verify_m_prime(&m[1], tx_ctx->strmsg, tx_ctx->strmsg_len);
if (ret)
return ret;
#endif
return ret;
}
int cap_protocol_msg(uint8_t msg_id,
uint8_t *msg,
size_t *msg_len,
uint32_t lk_type,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
/* todo: check upper boundary */
int ret = 0;
int (**proto_func)(uint8_t *, size_t *,
struct hdcp_tx_ctx *,
struct hdcp_rx_ctx *);
if (lk_type == HDCP_LINK_TYPE_IIA)
proto_func = proto_iia;
#if defined(CONFIG_HDCP2_DP_ENABLE)
else if(lk_type == HDCP_LINK_TYPE_DP)
proto_func = proto_dp;
#endif
else {
hdcp_err("invalid link type(%d)\n", lk_type);
return -1;
}
if (msg_id > 1) {
ret = proto_func[msg_id - 2](msg, msg_len, tx_ctx, rx_ctx);
return ret;
}
else
return -1;
}
int decap_protocol_msg(uint8_t msg_id,
uint8_t *msg,
size_t msg_len,
uint32_t lk_type,
struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
int ret = 0;
int (**proto_func)(uint8_t *, size_t *,
struct hdcp_tx_ctx *,
struct hdcp_rx_ctx *);
/* todo: check upper boundary */
if (lk_type == HDCP_LINK_TYPE_IIA)
proto_func = proto_iia;
#if defined(CONFIG_HDCP2_DP_ENABLE)
else if(lk_type == HDCP_LINK_TYPE_DP)
proto_func = proto_dp;
#endif
else {
hdcp_err("HDCP: invalid link type(%d)\n", lk_type);
return -1;
}
if (msg_id > 1) {
ret = proto_func[msg_id - 2](msg, &msg_len, tx_ctx, rx_ctx);
return ret;
}
else
return -1;
}