lineage_kernel_xcoverpro/drivers/soc/samsung/exynos-hdcp/iia_link/exynos-hdcp2-iia-auth.c

463 lines
11 KiB
C
Executable File

/*
* drivers/soc/samsung/exynos-hdcp/exynos-hdcp2-tx-auth.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 "exynos-hdcp2-iia-auth.h"
#include "../exynos-hdcp2-log.h"
#define HDCP_TX_VERSION_2_2 HDCP_TX_VERSION_2_1
static int next_step;
static int key_found;
static char *hdcp_msgid_str[] = {
NULL,
"Null message",
"AKE_Init",
"AKE_Send_Cert",
"AKE_No_Stored_km",
"AKE_Stored_km",
"AKE_Send_rrx",
"AKE_Send_H_prime",
"AKE_Send_Pairing_Info",
"LC_Init",
"LC_Send_L_prime",
"SKE_Send_Eks",
"RepeaterAuth_Send_ReceiverID_List",
"RTT_Ready",
"RTT_Challenge",
"RepeaterAuth_Send_Ack",
"RepeaterAuth_Stream_Manage",
"RepeaterAuth_Stream_Ready",
"Receiver_AuthStatus",
"AKE_Transmitter_Info",
"AKE_Receiver_Info",
NULL
};
#define is_precomput(lk) \
((lk->rx_ctx.version != HDCP_VERSION_2_0) && \
lk->tx_ctx.lc_precomp && \
lk->rx_ctx.lc_precomp)
static int send_protocol_msg(struct hdcp_link_data *lk, uint8_t msg_id, struct hdcp_msg_info *msg_info)
{
int ret = TX_AUTH_SUCCESS;
hdcp_info("Tx->Rx: %s\n", hdcp_msgid_str[msg_id]);
ret = cap_protocol_msg(msg_id, msg_info->msg, (size_t *)&msg_info->msg_len, lk->lk_type, &lk->tx_ctx, &lk->rx_ctx);
if (ret) {
hdcp_err("cap_protocol_msg() failed. ret(0x%08x)\n", ret);
return -TX_AUTH_ERROR_MAKE_PROTO_MSG;
}
return TX_AUTH_SUCCESS;
}
static int recv_protocol_msg(struct hdcp_link_data *lk, uint8_t msg_id, struct hdcp_msg_info *msg_info)
{
int ret = TX_AUTH_SUCCESS;
if (ret >= 0 && msg_info->msg_len > 0) {
/* parsing received message */
ret = decap_protocol_msg(msg_id, msg_info->msg, msg_info->msg_len, lk->lk_type, &lk->tx_ctx, &lk->rx_ctx);
if (ret) {
hdcp_err("dcap_protocol_msg() failed. msg_id(%d), ret(0x%08x)\n", msg_id, ret);
ret = -TX_AUTH_ERROR_WRONG_MSG;
}
}
hdcp_info("Rx->Tx: %s\n", hdcp_msgid_str[msg_id]);
return ret;
}
static int hdcp_ake_find_masterkey(struct hdcp_tx_ctx *tx_ctx,
struct hdcp_rx_ctx *rx_ctx)
{
/* todo */
return -1;
}
static int get_hdcp_session_key(struct hdcp_link_data *lk)
{
/* todo */
return 0;
}
static int put_hdcp_session_key(struct hdcp_link_data *lk)
{
/* todo */
return 0;
}
int exchange_master_key(struct hdcp_link_data *lk, struct hdcp_msg_info *msg_info)
{
int rval = TX_AUTH_SUCCESS;
if (next_step < AKE_INIT)
UPDATE_STEP_STATE(next_step, AKE_INIT);
switch (next_step) {
case AKE_INIT:
{
rval = send_protocol_msg(lk, AKE_INIT, msg_info);
if (rval < 0) {
hdcp_err("send AKE_Init failed. rval(%d)\n", rval);
} else {
UPDATE_STEP_STATE(next_step, AKE_TRANSMITTER_INFO);
#ifdef HDCP_TX_VERSION_2_2
msg_info->next_step = SEND_MSG;
#else
msg_info->next_step = RECIEVE_MSG;
#endif
}
break;
}
case AKE_TRANSMITTER_INFO:
{
#ifdef HDCP_TX_VERSION_2_2
rval = send_protocol_msg(lk, AKE_TRANSMITTER_INFO, msg_info);
if (rval < 0) {
hdcp_err("send AKE_Transmitter_Info failed. rval(%d)\n", rval);
} else {
UPDATE_STEP_STATE(next_step, AKE_SEND_CERT);
msg_info->next_step = RECIEVE_MSG;
}
break;
#endif
}
case AKE_SEND_CERT:
{
rval = recv_protocol_msg(lk, AKE_SEND_CERT, msg_info);
if (rval < 0) {
hdcp_err("recv AKE_Send_Cert failed. rval(%d)\n", rval);
} else {
UPDATE_STEP_STATE(next_step, AKE_RECEIVER_INFO);
msg_info->next_step = RECIEVE_MSG;
}
break;
}
case AKE_RECEIVER_INFO:
{
rval = recv_protocol_msg(lk, AKE_RECEIVER_INFO, msg_info);
if (rval < 0) {
hdcp_err("recv AKE_Receiver_Info failed. rval(%d)\n", rval);
} else {
UPDATE_STEP_STATE(next_step, AKE_NO_STORED_KM);
msg_info->next_step = SEND_MSG;
}
break;
}
case AKE_NO_STORED_KM:
{
key_found = hdcp_ake_find_masterkey(&lk->tx_ctx, &lk->rx_ctx);
if ((key_found < 0)) {
rval = send_protocol_msg(lk, AKE_NO_STORED_KM, msg_info);
if (rval < 0) {
hdcp_err("send AKE_No_Stored_km failed. rval(%d)\n", rval);
} else {
UPDATE_STEP_STATE(next_step, AKE_SEND_RRX);
msg_info->next_step = RECIEVE_MSG;
}
lk->stored_km = HDCP_WITHOUT_STORED_KM;
} else {
rval = send_protocol_msg(lk, AKE_STORED_KM, msg_info);
if (rval < 0) {
hdcp_err("send AKE_Stored_km failed. rval(%d)\n", rval);
} else {
UPDATE_STEP_STATE(next_step, AKE_SEND_RRX);
msg_info->next_step = RECIEVE_MSG;
}
lk->stored_km = HDCP_WITH_STORED_KM;
}
break;
}
case AKE_SEND_RRX:
{
rval = recv_protocol_msg(lk, AKE_SEND_RRX, msg_info);
if (rval < 0) {
hdcp_err("recv AKE_Send_rrx failed. rval(%d)\n", rval);
} else {
UPDATE_STEP_STATE(next_step, AKE_SEND_H_PRIME);
msg_info->next_step = RECIEVE_MSG;
}
break;
}
case AKE_SEND_H_PRIME:
{
rval = recv_protocol_msg(lk, AKE_SEND_H_PRIME, msg_info);
if (rval < 0) {
hdcp_err("recv AKE_Send_H_Prime failed. rval(%d)\n", rval);
} else {
UPDATE_STEP_STATE(next_step, AKE_SEND_PAIRING_INFO);
if(key_found == -1){
hdcp_debug("Key found\n");
msg_info->next_step = RECIEVE_MSG;
}
else {
hdcp_debug("Key not found\n");
msg_info->next_step = DONE;
}
}
break;
}
case AKE_SEND_PAIRING_INFO:
{
if (key_found == -1) {
rval = recv_protocol_msg(lk, AKE_SEND_PAIRING_INFO, msg_info);
if (rval < 0) {
hdcp_err("recv AKE_Send_Pairing_Info failed. rval(%d)\n", rval);
break;
}
}
msg_info->next_step = DONE;
UPDATE_STEP_STATE(next_step, LC_INIT);
break;
}
default:
return -ENOTTY;
}
if (rval != TX_AUTH_SUCCESS)
next_step = AKE_INIT;
return rval;
}
int locality_check(struct hdcp_link_data *lk, struct hdcp_msg_info *msg_info)
{
int rval = TX_AUTH_SUCCESS;
switch (next_step) {
case LC_INIT:
{
rval = send_protocol_msg(lk, LC_INIT, msg_info);
if (rval < 0) {
hdcp_err("send LC_Init failed. rval(%d)\n", rval);
break;
}
else {
UPDATE_STEP_STATE(next_step, RTT_READY);
msg_info->next_step = RECIEVE_MSG;
break;
}
}
case RTT_READY:
{
/* if no precompute */
if (!is_precomput(lk)) {
hdcp_debug("LC with no precompute\n");
rval = recv_protocol_msg(lk, LC_SEND_L_PRIME, msg_info);
if (rval == TX_AUTH_SUCCESS) {
UPDATE_STEP_STATE(next_step, AKE_INIT);
msg_info->next_step = DONE;
}
else {
hdcp_err("recv LC_Send_L_prime failed. rval(%d)\n", rval);
}
break;
} else {
/* if precompute */
rval = recv_protocol_msg(lk, RTT_READY, msg_info);
if (rval < 0) {
hdcp_err("recv RTT_Ready failed. rval(%d)\n", rval);
}
else {
UPDATE_STEP_STATE(next_step, RTT_CHALLENGE);
msg_info->next_step = SEND_MSG;
}
break;
}
}
case RTT_CHALLENGE:
{
rval = send_protocol_msg(lk, RTT_CHALLENGE, msg_info);
if (rval < 0) {
hdcp_err("send RTT_Challenge failed. rval(%d)\n", rval);
}
else {
UPDATE_STEP_STATE(next_step, LC_SEND_L_PRIME);
msg_info->next_step = RECIEVE_MSG;
}
break;
}
case LC_SEND_L_PRIME:
{
rval = recv_protocol_msg(lk, LC_SEND_L_PRIME, msg_info);
if (rval == TX_AUTH_SUCCESS){
msg_info->next_step = DONE;
if (evaluate_repeater(lk))
UPDATE_STEP_STATE(next_step, REPEATERAUTH_SEND_RECEIVERID_LIST);
else
UPDATE_STEP_STATE(next_step, AKE_INIT);
}
else {
hdcp_err("recv LC_Send_L_prime failed. rval(%d)\n", rval);
}
break;
}
default:
return -ENOTTY;
}
return rval;
}
int exchange_hdcp_session_key(struct hdcp_link_data *lk, struct hdcp_msg_info *msg_info)
{
int rval = TX_AUTH_SUCCESS;
/* find session key from the session data */
if (get_hdcp_session_key(lk) < 0) {
hdcp_err("get_hdcp_session_key() failed\n");
rval = -TX_AUTH_ERRRO_RESTORE_SKEY;
}
rval = send_protocol_msg(lk, SKE_SEND_EKS, msg_info);
if (rval < 0)
hdcp_err("send SKE_Send_Eks() failed\n");
if (put_hdcp_session_key(lk) < 0) {
hdcp_err("put_hdcp_session_key() failed\n");
rval = -TX_AUTH_ERROR_STORE_SKEY;
}
return rval;
}
int evaluate_repeater(struct hdcp_link_data *lk)
{
if (lk->rx_ctx.repeater == REPEATER)
return TRUE;
else
return FALSE;
}
int wait_for_receiver_id_list(struct hdcp_link_data *lk, struct hdcp_msg_info *msg_info)
{
int rval = TX_AUTH_SUCCESS;
rval = recv_protocol_msg(lk, REPEATERAUTH_SEND_RECEIVERID_LIST, msg_info);
if (rval < 0) {
hdcp_err("recv RepeaterAuth_Send_ReceiverID_List failed. rval(%d)\n", rval);
return rval;
}
UPDATE_STEP_STATE(next_step, REPEATERAUTH_SEND_ACK);
return rval;
}
int send_receiver_id_list_ack(struct hdcp_link_data *lk, struct hdcp_msg_info *msg_info)
{
int rval = TX_AUTH_SUCCESS;
switch (next_step) {
case REPEATERAUTH_SEND_ACK:
{
rval = send_protocol_msg(lk, REPEATERAUTH_SEND_ACK, msg_info);
if (rval < 0) {
hdcp_err("send RepeaterAuth_Send_Ack() failed. rval(%d)\n", rval);
}
else {
UPDATE_STEP_STATE(next_step, RECEIVER_AUTHSTATUS);
msg_info->next_step = RP_RECIEVE_MSG;
}
break;
}
case RECEIVER_AUTHSTATUS:
{
rval = recv_protocol_msg(lk, RECEIVER_AUTHSTATUS, msg_info);
if (rval < 0) {
hdcp_err("send Receiver_AuthStatus() failed. rval(%d)\n", rval);
}
else {
UPDATE_STEP_STATE(next_step, REPEATERAUTH_STREAM_MANAGE);
msg_info->next_step = DONE;
}
break;
}
default:
return -ENOTTY;
}
if (lk->tx_ctx.rp_reauth) {
hdcp_err("receiver request reauthentication\n");
return -TX_AUTH_ERROR_TIME_EXCEED;
}
else
hdcp_err("Repeater send reAuth value:: %d\n", lk->tx_ctx.rp_reauth);
return rval;
}
int manage_content_stream(struct hdcp_link_data *lk, struct contents_info *stream_ctrl, struct hdcp_stream_info *stream_info)
{
int rval = TX_AUTH_SUCCESS;
struct hdcp_msg_info msg_info;
if (stream_info->msg_len < sizeof(msg_info.msg) && stream_info->msg_len > 0)
msg_info.msg_len = stream_info->msg_len;
else
return HDCP_ERROR_INVALID_STREAM_LEN;
memcpy(msg_info.msg, stream_info->msg, stream_info->msg_len);
switch (next_step) {
case REPEATERAUTH_STREAM_MANAGE:
{
memcpy(&lk->tx_ctx.stream_ctrl, stream_ctrl, sizeof(struct contents_info));
rval = send_protocol_msg(lk, REPEATERAUTH_STREAM_MANAGE, &msg_info);
if (rval < 0) {
hdcp_err("send RepeaterAuth_stream_manage() failed. rval(%d)\n", rval);
break;
}
else {
UPDATE_STEP_STATE(next_step, REPEATERAUTH_STREAM_READY);
stream_info->next_step = ST_RECIEVE_MSG;
if (msg_info.msg_len > STREAM_MAX_LEN) {
hdcp_err("send RepeaterAuth_stream_manage() failed. rval(%d)\n", rval);
return TX_AUTH_ERROR_WRONG_MSG;
}
memcpy(stream_info->msg, msg_info.msg, msg_info.msg_len);
stream_info->msg_len = msg_info.msg_len;
break;
}
}
case REPEATERAUTH_STREAM_READY:
{
rval = recv_protocol_msg(lk, REPEATERAUTH_STREAM_READY, &msg_info);
if (rval < 0) {
hdcp_err("send Receiver_AuthStatus() failed. rval(%d)\n", rval);
break;
}
else {
UPDATE_STEP_STATE(next_step, AKE_INIT);
stream_info->next_step = RP_FINISHED;
break;
}
if (msg_info.msg_len < sizeof(stream_info->msg) && msg_info.msg_len > 0)
memcpy(stream_info->msg, msg_info.msg, msg_info.msg_len);
}
default:
return -ENOTTY;
}
return TX_AUTH_SUCCESS;
}
int determine_rx_hdcp_cap(struct hdcp_link_data *lk)
{
/* todo */
return 0;
}