blob: 772abaa3f5cfec516216cbff0892adacb381c053 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd.
*
* Samsung DisplayPort driver.
*
* 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 <drm/drm_dp_helper.h>
#include <linux/kernel.h>
#include "auth22-internal.h"
#include "dpcd.h"
#include "teeif.h"
#include "hdcp-log.h"
#define MAX_LC_RETRY 10
static int do_send_lc_init(struct hdcp_link_data *lk)
{
int ret;
uint8_t rn[HDCP_RTX_BYTE_LEN];
if (lk->is_aborted)
return -ECANCELED;
ret = teei_gen_rn(rn, sizeof(rn));
if (ret) {
hdcp_err("teei_gen_rn failed (%d)\n", ret);
return -EIO;
}
ret = hdcp_dplink_send(DP_HDCP_2_2_REG_RN_OFFSET, rn, sizeof(rn));
if (ret) {
hdcp_err("rn send fail: ret(%d)\n", ret);
return -EIO;
}
return 0;
}
static int do_recv_lc_send_l_prime(struct hdcp_link_data *lk)
{
int ret;
uint8_t lprime[HDCP_HMAC_SHA256_LEN];
if (lk->is_aborted)
return -ECANCELED;
ret = hdcp_dplink_recv(DP_HDCP_2_2_REG_LPRIME_OFFSET, lprime,
sizeof(lprime));
if (ret) {
hdcp_err("l_prime recv fail. ret(%d)\n", ret);
return -EIO;
}
ret = teei_compare_lc_hmac(lprime, sizeof(lprime));
if (ret) {
hdcp_err("teei_compare_lc_hmac failed (%d).\n", ret);
return -EIO;
}
return 0;
}
int auth22_locality_check(struct hdcp_link_data *lk)
{
int i;
for (i = 0; i < MAX_LC_RETRY; i++) {
/* send Tx -> Rx: LC_init */
if (do_send_lc_init(lk) < 0) {
hdcp_err("send_lc_init fail\n");
return -EIO;
}
/* wait until max dealy */
msleep(16);
/* recv Rx -> Tx: LC_Send_L_Prime */
if (do_recv_lc_send_l_prime(lk) < 0) {
hdcp_err("recv_lc_send_l_prime fail\n");
/* retry */
continue;
} else {
hdcp_debug("LC success. retryed(%d)\n", i);
break;
}
}
if (i == MAX_LC_RETRY) {
hdcp_err("LC check fail. exceed retry count(%d)\n", i);
return -EFAULT;
}
return 0;
}