mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
hdmitx: adjust hdmitx related code [1/2]
PD#173252: hdmitx: adjust hdmitx related code Change-Id: Ie8dfd4b21055b9ab34b50efca65dfafa78f2254d Signed-off-by: Zongdong Jiao <zongdong.jiao@amlogic.com>
This commit is contained in:
committed by
Jianxin Pan
parent
00ff0c7669
commit
ee2c15ae28
@@ -13538,9 +13538,9 @@ M: Tao Zeng <tao.zeng@amlogic.com>
|
||||
F: arch/arm/mach-meson/Makefile.boot
|
||||
|
||||
HDMITX OUTPUT DRIVER
|
||||
M: Zongdong Jiao <zongdong.jiao@amlogic.com>
|
||||
M: Yi Zhou <yi.zhou@amlogic.com>
|
||||
M: Kaifu Hu <kaifu.hu@amlogic.com>
|
||||
M: Zongdong Jiao <zongdong.jiao@amlogic.com>
|
||||
S: Maintained
|
||||
F: drivers/amlogic/media/vout/hdmitx/*
|
||||
F: drivers/amlogic/media/vout/hdmitx/hdcp/*
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
obj-y += hdmi_tx_hw.o reg_ops.o enc_cfg_hw.o hdmi_tx_ddc.o hdcpVerify.o
|
||||
obj-y += hdmi_tx_hw.o reg_ops.o enc_cfg_hw.o hdmi_tx_ddc.o checksha.o
|
||||
obj-y += hw_gxbb.o hw_gxtvbb.o hw_gxl.o hw_txlx.o hw_clk.o hw_g12a.o
|
||||
|
||||
200
drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.c
Normal file
200
drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/string.h>
|
||||
#include "checksha.h"
|
||||
|
||||
static void shamsg_reset(struct shamsg_t *msg)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
msg->shamsg_idx = 0;
|
||||
msg->shamsg_cmp = FALSE;
|
||||
msg->shamsg_crp = FALSE;
|
||||
for (i = 0; i < sizeof(msg->shamsg_len); i++)
|
||||
msg->shamsg_len[i] = 0;
|
||||
|
||||
msg->shamsg_dgt[0] = SHA_CONST_VAL0;
|
||||
msg->shamsg_dgt[1] = SHA_CONST_VAL1;
|
||||
msg->shamsg_dgt[2] = SHA_CONST_VAL2;
|
||||
msg->shamsg_dgt[3] = SHA_CONST_VAL3;
|
||||
msg->shamsg_dgt[4] = SHA_CONST_VAL4;
|
||||
}
|
||||
|
||||
static void shamsg_calcblock(struct shamsg_t *msg)
|
||||
{
|
||||
const unsigned int K[] = {
|
||||
SHA_CONST_K0,
|
||||
SHA_CONST_K1,
|
||||
SHA_CONST_K2,
|
||||
SHA_CONST_K3
|
||||
};
|
||||
unsigned int W[80];
|
||||
unsigned int A, B, C, D, E;
|
||||
unsigned int temp = 0;
|
||||
int t = 0;
|
||||
|
||||
#define SHIFT_DAT(idx, off) \
|
||||
(((unsigned int)msg->shamsg_blk[t * 4 + idx]) << off)
|
||||
|
||||
for (t = 0; t < 80; t++) {
|
||||
if (t < 16) {
|
||||
W[t] = SHIFT_DAT(0, 24);
|
||||
W[t] |= SHIFT_DAT(1, 16);
|
||||
W[t] |= SHIFT_DAT(2, 8);
|
||||
W[t] |= SHIFT_DAT(3, 0);
|
||||
} else
|
||||
W[t] = SHAMSG_SHIFT(1, W[t-3]^W[t-8]^W[t-14]^W[t-16]);
|
||||
}
|
||||
|
||||
A = msg->shamsg_dgt[0];
|
||||
B = msg->shamsg_dgt[1];
|
||||
C = msg->shamsg_dgt[2];
|
||||
D = msg->shamsg_dgt[3];
|
||||
E = msg->shamsg_dgt[4];
|
||||
|
||||
for (t = 0; t < 80; t++) {
|
||||
temp = SHAMSG_SHIFT(5, A);
|
||||
if (t < 20)
|
||||
temp += ((B & C) | ((~B) & D)) + E + W[t] + K[0];
|
||||
else if (t < 40)
|
||||
temp += (B ^ C ^ D) + E + W[t] + K[1];
|
||||
else if (t < 60)
|
||||
temp += ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
|
||||
else
|
||||
temp += (B ^ C ^ D) + E + W[t] + K[3];
|
||||
E = D;
|
||||
D = C;
|
||||
C = SHAMSG_SHIFT(30, B);
|
||||
B = A;
|
||||
A = (temp & MAX_VAL_MASK);
|
||||
}
|
||||
|
||||
msg->shamsg_dgt[0] = (msg->shamsg_dgt[0] + A) & MAX_VAL_MASK;
|
||||
msg->shamsg_dgt[1] = (msg->shamsg_dgt[1] + B) & MAX_VAL_MASK;
|
||||
msg->shamsg_dgt[2] = (msg->shamsg_dgt[2] + C) & MAX_VAL_MASK;
|
||||
msg->shamsg_dgt[3] = (msg->shamsg_dgt[3] + D) & MAX_VAL_MASK;
|
||||
msg->shamsg_dgt[4] = (msg->shamsg_dgt[4] + E) & MAX_VAL_MASK;
|
||||
|
||||
msg->shamsg_idx = 0;
|
||||
}
|
||||
|
||||
static void shamsg_init(struct shamsg_t *msg,
|
||||
const unsigned char *data, int size)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned int j = 0;
|
||||
int rc = TRUE;
|
||||
|
||||
if (data == NULL || size == 0) {
|
||||
pr_info("invalid parameters\n");
|
||||
return;
|
||||
}
|
||||
if (msg->shamsg_cmp == TRUE || msg->shamsg_crp == TRUE) {
|
||||
msg->shamsg_crp = TRUE;
|
||||
return;
|
||||
}
|
||||
while (size-- && msg->shamsg_crp == FALSE) {
|
||||
msg->shamsg_blk[msg->shamsg_idx++] = *data;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
rc = TRUE;
|
||||
for (j = 0; j < sizeof(msg->shamsg_len); j++) {
|
||||
msg->shamsg_len[j]++;
|
||||
if (msg->shamsg_len[j] != 0) {
|
||||
rc = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
msg->shamsg_crp = (msg->shamsg_crp == TRUE ||
|
||||
rc == TRUE) ? TRUE : FALSE;
|
||||
}
|
||||
if (msg->shamsg_idx == 64)
|
||||
shamsg_calcblock(msg);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
static void shamsg_padmsg(struct shamsg_t *msg)
|
||||
{
|
||||
if (msg->shamsg_idx > 55) {
|
||||
msg->shamsg_blk[msg->shamsg_idx++] = 0x80;
|
||||
while (msg->shamsg_idx < 64)
|
||||
msg->shamsg_blk[msg->shamsg_idx++] = 0;
|
||||
shamsg_calcblock(msg);
|
||||
while (msg->shamsg_idx < 56)
|
||||
msg->shamsg_blk[msg->shamsg_idx++] = 0;
|
||||
} else {
|
||||
msg->shamsg_blk[msg->shamsg_idx++] = 0x80;
|
||||
while (msg->shamsg_idx < 56)
|
||||
msg->shamsg_blk[msg->shamsg_idx++] = 0;
|
||||
}
|
||||
|
||||
msg->shamsg_blk[56] = msg->shamsg_len[7];
|
||||
msg->shamsg_blk[57] = msg->shamsg_len[6];
|
||||
msg->shamsg_blk[58] = msg->shamsg_len[5];
|
||||
msg->shamsg_blk[59] = msg->shamsg_len[4];
|
||||
msg->shamsg_blk[60] = msg->shamsg_len[3];
|
||||
msg->shamsg_blk[61] = msg->shamsg_len[2];
|
||||
msg->shamsg_blk[62] = msg->shamsg_len[1];
|
||||
msg->shamsg_blk[63] = msg->shamsg_len[0];
|
||||
|
||||
shamsg_calcblock(msg);
|
||||
}
|
||||
|
||||
static int get_shamsg_result(struct shamsg_t *msg)
|
||||
{
|
||||
if (msg->shamsg_crp == TRUE)
|
||||
return FALSE;
|
||||
if (msg->shamsg_crp == FALSE) {
|
||||
shamsg_padmsg(msg);
|
||||
msg->shamsg_crp = TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int calc_hdcp_ksv_valid(const unsigned char *data, int size)
|
||||
{
|
||||
int i = 0;
|
||||
struct shamsg_t shamsg;
|
||||
|
||||
memset(&shamsg, 0, sizeof(struct shamsg_t));
|
||||
|
||||
if (data == NULL || size < (HDCP_HEAD + SHA_MAX_SIZE)) {
|
||||
pr_info("invalid parameters\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
shamsg_reset(&shamsg);
|
||||
shamsg_init(&shamsg, data, size - SHA_MAX_SIZE);
|
||||
if (get_shamsg_result(&shamsg) == FALSE) {
|
||||
pr_info("hdcp invalid ksv/sha message\n");
|
||||
return FALSE;
|
||||
}
|
||||
for (i = 0; i < SHA_MAX_SIZE; i++) {
|
||||
if (data[size - SHA_MAX_SIZE + i] !=
|
||||
(uint8_t)(shamsg.shamsg_dgt[i / 4]
|
||||
>> ((i % 4) * 8))) {
|
||||
pr_info("hdcp ksv/sha not match\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
59
drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.h
Normal file
59
drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CHECKSHA_H__
|
||||
#define __CHECKSHA_H__
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define HDCP_NULL 0
|
||||
#define HDCP_KSVLIST_VALID 1
|
||||
#define HDCP_KSVLIST_INVALID 2
|
||||
|
||||
#define KSV_SIZE 5
|
||||
#define HDCP_HEAD 10
|
||||
#define SHA_MAX_SIZE 20
|
||||
#define KSV_MASK 0x7F
|
||||
#define MAX_VAL_MASK 0xFFFFFFFF
|
||||
|
||||
#define SHA_CONST_VAL0 0x67452301
|
||||
#define SHA_CONST_VAL1 0xEFCDAB89
|
||||
#define SHA_CONST_VAL2 0x98BADCFE
|
||||
#define SHA_CONST_VAL3 0x10325476
|
||||
#define SHA_CONST_VAL4 0xC3D2E1F0
|
||||
|
||||
#define SHA_CONST_K0 0x5A827999
|
||||
#define SHA_CONST_K1 0x6ED9EBA1
|
||||
#define SHA_CONST_K2 0x8F1BBCDC
|
||||
#define SHA_CONST_K3 0xCA62C1D6
|
||||
|
||||
struct shamsg_t {
|
||||
unsigned char shamsg_len[8];
|
||||
unsigned char shamsg_blk[64];
|
||||
int shamsg_idx;
|
||||
int shamsg_cmp;
|
||||
int shamsg_crp;
|
||||
unsigned int shamsg_dgt[5];
|
||||
};
|
||||
|
||||
#define SHAMSG_SHIFT(bit, val) \
|
||||
((((val) << (bit)) & 0xFFFFFFFF) | ((val) >> (32-(bit))))
|
||||
|
||||
int calc_hdcp_ksv_valid(const unsigned char *dat, int size);
|
||||
|
||||
#endif /* __CHECKSHA_H__ */
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcp.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HDCP_H_
|
||||
#define HDCP_H_
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
enum hdcp_status_t {
|
||||
HDCP_IDLE = 0,
|
||||
HDCP_KSV_LIST_READY,
|
||||
HDCP_ERR_KSV_LIST_NOT_VALID,
|
||||
HDCP_KSV_LIST_ERR_DEPTH_EXCEEDED,
|
||||
HDCP_KSV_LIST_ERR_MEM_ACCESS,
|
||||
HDCP_ENGAGED,
|
||||
HDCP_FAILED
|
||||
};
|
||||
|
||||
/* HDCP Interrupt bit fields */
|
||||
#define INT_KSV_ACCESS (0)
|
||||
#define INT_KSV_SHA1 (1)
|
||||
#define INT_HDCP_FAIL (6)
|
||||
#define INT_HDCP_ENGAGED (7)
|
||||
|
||||
#endif /* HDCP_H_ */
|
||||
@@ -1,600 +0,0 @@
|
||||
/*
|
||||
* drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hdcpVerify.h"
|
||||
|
||||
#define SIZE (160/8)
|
||||
#define KSIZE (1024/8)
|
||||
|
||||
void sha_Reset(struct sha_t *sha)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
sha->mIndex = 0;
|
||||
sha->mComputed = FALSE;
|
||||
sha->mCorrupted = FALSE;
|
||||
for (i = 0; i < sizeof(sha->mLength); i++)
|
||||
sha->mLength[i] = 0;
|
||||
sha->mDigest[0] = 0x67452301;
|
||||
sha->mDigest[1] = 0xEFCDAB89;
|
||||
sha->mDigest[2] = 0x98BADCFE;
|
||||
sha->mDigest[3] = 0x10325476;
|
||||
sha->mDigest[4] = 0xC3D2E1F0;
|
||||
}
|
||||
|
||||
int sha_Result(struct sha_t *sha)
|
||||
{
|
||||
if (sha->mCorrupted == TRUE)
|
||||
return FALSE;
|
||||
if (sha->mComputed == FALSE) {
|
||||
sha_PadMessage(sha);
|
||||
sha->mComputed = TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void sha_Input(struct sha_t *sha, const uint8_t *data, size_t size)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned int j = 0;
|
||||
int rc = TRUE;
|
||||
|
||||
if (data == 0 || size == 0) {
|
||||
pr_info("invalid input data");
|
||||
return;
|
||||
}
|
||||
if (sha->mComputed == TRUE || sha->mCorrupted == TRUE) {
|
||||
sha->mCorrupted = TRUE;
|
||||
return;
|
||||
}
|
||||
while (size-- && sha->mCorrupted == FALSE) {
|
||||
sha->mBlock[sha->mIndex++] = *data;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
rc = TRUE;
|
||||
for (j = 0; j < sizeof(sha->mLength); j++) {
|
||||
sha->mLength[j]++;
|
||||
if (sha->mLength[j] != 0) {
|
||||
rc = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sha->mCorrupted = (sha->mCorrupted == TRUE ||
|
||||
rc == TRUE) ? TRUE : FALSE;
|
||||
}
|
||||
/* if corrupted then message is too long */
|
||||
if (sha->mIndex == 64)
|
||||
sha_ProcessBlock(sha);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
void sha_ProcessBlock(struct sha_t *sha)
|
||||
{
|
||||
#define shaCircularShift(bits, word) \
|
||||
((((word) << (bits)) & 0xFFFFFFFF) | ((word) >> (32-(bits))))
|
||||
|
||||
const unsigned int K[] = {
|
||||
/* constants defined in SHA-1 */
|
||||
0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
|
||||
unsigned int W[80]; /* word sequence */
|
||||
unsigned int A, B, C, D, E; /* word buffers */
|
||||
unsigned int temp = 0;
|
||||
int t = 0;
|
||||
|
||||
/* Initialize the first 16 words in the array W */
|
||||
for (t = 0; t < 80; t++) {
|
||||
if (t < 16) {
|
||||
W[t] = ((unsigned int) sha->mBlock[t * 4 + 0]) << 24;
|
||||
W[t] |= ((unsigned int) sha->mBlock[t * 4 + 1]) << 16;
|
||||
W[t] |= ((unsigned int) sha->mBlock[t * 4 + 2]) << 8;
|
||||
W[t] |= ((unsigned int) sha->mBlock[t * 4 + 3]) << 0;
|
||||
} else
|
||||
W[t] = shaCircularShift(1,
|
||||
W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
|
||||
}
|
||||
|
||||
A = sha->mDigest[0];
|
||||
B = sha->mDigest[1];
|
||||
C = sha->mDigest[2];
|
||||
D = sha->mDigest[3];
|
||||
E = sha->mDigest[4];
|
||||
|
||||
for (t = 0; t < 80; t++) {
|
||||
temp = shaCircularShift(5, A);
|
||||
if (t < 20)
|
||||
temp += ((B & C) | ((~B) & D)) + E + W[t] + K[0];
|
||||
else if (t < 40)
|
||||
temp += (B ^ C ^ D) + E + W[t] + K[1];
|
||||
else if (t < 60)
|
||||
temp += ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
|
||||
else
|
||||
temp += (B ^ C ^ D) + E + W[t] + K[3];
|
||||
E = D;
|
||||
D = C;
|
||||
C = shaCircularShift(30, B);
|
||||
B = A;
|
||||
A = (temp & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
sha->mDigest[0] = (sha->mDigest[0] + A) & 0xFFFFFFFF;
|
||||
sha->mDigest[1] = (sha->mDigest[1] + B) & 0xFFFFFFFF;
|
||||
sha->mDigest[2] = (sha->mDigest[2] + C) & 0xFFFFFFFF;
|
||||
sha->mDigest[3] = (sha->mDigest[3] + D) & 0xFFFFFFFF;
|
||||
sha->mDigest[4] = (sha->mDigest[4] + E) & 0xFFFFFFFF;
|
||||
|
||||
sha->mIndex = 0;
|
||||
}
|
||||
|
||||
void sha_PadMessage(struct sha_t *sha)
|
||||
{
|
||||
/*
|
||||
* Check to see if the current message block is too small to hold
|
||||
* the initial padding bits and length. If so, we will pad the
|
||||
* block, process it, and then continue padding into a second
|
||||
* block.
|
||||
*/
|
||||
if (sha->mIndex > 55) {
|
||||
sha->mBlock[sha->mIndex++] = 0x80;
|
||||
while (sha->mIndex < 64)
|
||||
sha->mBlock[sha->mIndex++] = 0;
|
||||
sha_ProcessBlock(sha);
|
||||
while (sha->mIndex < 56)
|
||||
sha->mBlock[sha->mIndex++] = 0;
|
||||
} else {
|
||||
sha->mBlock[sha->mIndex++] = 0x80;
|
||||
while (sha->mIndex < 56)
|
||||
sha->mBlock[sha->mIndex++] = 0;
|
||||
}
|
||||
|
||||
/* Store the message length as the last 8 octets */
|
||||
sha->mBlock[56] = sha->mLength[7];
|
||||
sha->mBlock[57] = sha->mLength[6];
|
||||
sha->mBlock[58] = sha->mLength[5];
|
||||
sha->mBlock[59] = sha->mLength[4];
|
||||
sha->mBlock[60] = sha->mLength[3];
|
||||
sha->mBlock[61] = sha->mLength[2];
|
||||
sha->mBlock[62] = sha->mLength[1];
|
||||
sha->mBlock[63] = sha->mLength[0];
|
||||
|
||||
sha_ProcessBlock(sha);
|
||||
}
|
||||
|
||||
int hdcpVerify_DSA(const uint8_t *M, size_t n, const uint8_t *r,
|
||||
const uint8_t *s)
|
||||
{
|
||||
int i = 0;
|
||||
struct sha_t sha;
|
||||
static const uint8_t q[] = {
|
||||
0xE7, 0x08, 0xC7, 0xF9, 0x4D, 0x3F, 0xEF, 0x97,
|
||||
0xE2, 0x14, 0x6D, 0xCD, 0x6A, 0xB5, 0x6D, 0x5E,
|
||||
0xCE, 0xF2, 0x8A, 0xEE };
|
||||
static const uint8_t p[] = {
|
||||
0x27, 0x75, 0x28, 0xF3, 0x2B, 0x80, 0x59, 0x8C,
|
||||
0x11, 0xC2, 0xED, 0x46, 0x1C, 0x95, 0x39, 0x2A,
|
||||
0x54, 0x19, 0x89, 0x96, 0xFD, 0x49, 0x8A, 0x02,
|
||||
0x3B, 0x73, 0x75, 0x32, 0x14, 0x9C, 0x7B, 0x5C,
|
||||
0x49, 0x20, 0x98, 0xB9, 0x07, 0x32, 0x3F, 0xA7,
|
||||
0x30, 0x15, 0x72, 0xB3, 0x09, 0x55, 0x71, 0x10,
|
||||
0x3A, 0x4C, 0x97, 0xD1, 0xBC, 0xA0, 0x04, 0xF4,
|
||||
0x35, 0xCF, 0x47, 0x54, 0x0E, 0xA7, 0x2B, 0xE5,
|
||||
0x83, 0xB9, 0xC6, 0xD4, 0x47, 0xC7, 0x44, 0xB8,
|
||||
0x67, 0x76, 0x7C, 0xAE, 0x0C, 0xDC, 0x34, 0x4F,
|
||||
0x4B, 0x9E, 0x96, 0x1D, 0x82, 0x84, 0xD2, 0xA0,
|
||||
0xDC, 0xE0, 0x00, 0xF5, 0x64, 0xA1, 0x7F, 0x8E,
|
||||
0xFF, 0x58, 0x70, 0x6A, 0xC3, 0x4F, 0xA2, 0xA1,
|
||||
0xB8, 0xC7, 0x52, 0x5A, 0x35, 0x5B, 0x39, 0x17,
|
||||
0x6B, 0x78, 0x43, 0x93, 0xF7, 0x75, 0x8D, 0x01,
|
||||
0xB7, 0x61, 0x17, 0xFD, 0xB2, 0xF5, 0xC3, 0xD3 };
|
||||
static const uint8_t g[] = {
|
||||
0xD9, 0x0B, 0xBA, 0xC2, 0x42, 0x24, 0x46, 0x69,
|
||||
0x5B, 0x40, 0x67, 0x2F, 0x5B, 0x18, 0x3F, 0xB9,
|
||||
0xE8, 0x6F, 0x21, 0x29, 0xAC, 0x7D, 0xFA, 0x51,
|
||||
0xC2, 0x9D, 0x4A, 0xAB, 0x8A, 0x9B, 0x8E, 0xC9,
|
||||
0x42, 0x42, 0xA5, 0x1D, 0xB2, 0x69, 0xAB, 0xC8,
|
||||
0xE3, 0xA5, 0xC8, 0x81, 0xBE, 0xB6, 0xA0, 0xB1,
|
||||
0x7F, 0xBA, 0x21, 0x2C, 0x64, 0x35, 0xC8, 0xF7,
|
||||
0x5F, 0x58, 0x78, 0xF7, 0x45, 0x29, 0xDD, 0x92,
|
||||
0x9E, 0x79, 0x3D, 0xA0, 0x0C, 0xCD, 0x29, 0x0E,
|
||||
0xA9, 0xE1, 0x37, 0xEB, 0xBF, 0xC6, 0xED, 0x8E,
|
||||
0xA8, 0xFF, 0x3E, 0xA8, 0x7D, 0x97, 0x62, 0x51,
|
||||
0xD2, 0xA9, 0xEC, 0xBD, 0x4A, 0xB1, 0x5D, 0x8F,
|
||||
0x11, 0x86, 0x27, 0xCD, 0x66, 0xD7, 0x56, 0x5D,
|
||||
0x31, 0xD7, 0xBE, 0xA9, 0xAC, 0xDE, 0xAF, 0x02,
|
||||
0xB5, 0x1A, 0xDE, 0x45, 0x24, 0x3E, 0xE4, 0x1A,
|
||||
0x13, 0x52, 0x4D, 0x6A, 0x1B, 0x5D, 0xF8, 0x92 };
|
||||
static const uint8_t y[] = {
|
||||
0x99, 0x37, 0xE5, 0x36, 0xFA, 0xF7, 0xA9, 0x62,
|
||||
0x83, 0xFB, 0xB3, 0xE9, 0xF7, 0x9D, 0x8F, 0xD8,
|
||||
0xCB, 0x62, 0xF6, 0x66, 0x8D, 0xDC, 0xC8, 0x95,
|
||||
0x10, 0x24, 0x6C, 0x88, 0xBD, 0xFF, 0xB7, 0x7B,
|
||||
0xE2, 0x06, 0x52, 0xFD, 0xF7, 0x5F, 0x43, 0x62,
|
||||
0xE6, 0x53, 0x65, 0xB1, 0x38, 0x90, 0x25, 0x87,
|
||||
0x8D, 0xA4, 0x9E, 0xFE, 0x56, 0x08, 0xA7, 0xA2,
|
||||
0x0D, 0x4E, 0xD8, 0x43, 0x3C, 0x97, 0xBA, 0x27,
|
||||
0x6C, 0x56, 0xC4, 0x17, 0xA4, 0xB2, 0x5C, 0x8D,
|
||||
0xDB, 0x04, 0x17, 0x03, 0x4F, 0xE1, 0x22, 0xDB,
|
||||
0x74, 0x18, 0x54, 0x1B, 0xDE, 0x04, 0x68, 0xE1,
|
||||
0xBD, 0x0B, 0x4F, 0x65, 0x48, 0x0E, 0x95, 0x56,
|
||||
0x8D, 0xA7, 0x5B, 0xF1, 0x55, 0x47, 0x65, 0xE7,
|
||||
0xA8, 0x54, 0x17, 0x8A, 0x65, 0x76, 0x0D, 0x4F,
|
||||
0x0D, 0xFF, 0xAC, 0xA3, 0xE0, 0xFB, 0x80, 0x3A,
|
||||
0x86, 0xB0, 0xA0, 0x6B, 0x52, 0x00, 0x06, 0xC7 };
|
||||
uint8_t w[SIZE];
|
||||
uint8_t z[SIZE];
|
||||
uint8_t u1[SIZE];
|
||||
uint8_t u2[SIZE];
|
||||
uint8_t gu1[KSIZE];
|
||||
uint8_t yu2[KSIZE];
|
||||
uint8_t pro[KSIZE];
|
||||
uint8_t v[SIZE];
|
||||
|
||||
/* adapt to the expected format by arithmetic functions */
|
||||
uint8_t r1[SIZE];
|
||||
uint8_t s1[SIZE];
|
||||
|
||||
sha_Reset(&sha);
|
||||
hdcpVerify_ArrayCPY(r1, r, sizeof(r1));
|
||||
hdcpVerify_ArrayCPY(s1, s, sizeof(s1));
|
||||
hdcpVerify_ArraySWP(r1, sizeof(r1));
|
||||
hdcpVerify_ArraySWP(s1, sizeof(s1));
|
||||
|
||||
hdcpVerify_ComputeINV(w, s1, q, sizeof(w));
|
||||
sha_Input(&sha, M, n);
|
||||
if (sha_Result(&sha) == TRUE) {
|
||||
for (i = 0; i < 5; i++) {
|
||||
z[i * 4 + 0] = sha.mDigest[i] >> 24;
|
||||
z[i * 4 + 1] = sha.mDigest[i] >> 16;
|
||||
z[i * 4 + 2] = sha.mDigest[i] >> 8;
|
||||
z[i * 4 + 3] = sha.mDigest[i] >> 0;
|
||||
}
|
||||
hdcpVerify_ArraySWP(z, sizeof(z));
|
||||
} else {
|
||||
pr_info("cannot digest message");
|
||||
return FALSE;
|
||||
}
|
||||
if (hdcpVerify_ComputeMUL(u1, z, w, q, sizeof(u1)) == FALSE)
|
||||
return FALSE;
|
||||
if (hdcpVerify_ComputeMUL(u2, r1, w, q, sizeof(u2)) == FALSE)
|
||||
return FALSE;
|
||||
if (hdcpVerify_ComputeEXP(gu1, g, u1, p, sizeof(gu1), sizeof(u1))
|
||||
== FALSE)
|
||||
return FALSE;
|
||||
if (hdcpVerify_ComputeEXP(yu2, y, u2, p, sizeof(yu2), sizeof(u2))
|
||||
== FALSE)
|
||||
return FALSE;
|
||||
if (hdcpVerify_ComputeMUL(pro, gu1, yu2, p, sizeof(pro)) == FALSE)
|
||||
return FALSE;
|
||||
if (hdcpVerify_ComputeMOD(v, pro, q, sizeof(v)) == FALSE)
|
||||
return FALSE;
|
||||
return hdcpVerify_ArrayCMP(v, r1, sizeof(v)) == 0;
|
||||
}
|
||||
|
||||
int hdcpVerify_ArrayADD(uint8_t *r, const uint8_t *a, const uint8_t *b,
|
||||
size_t n)
|
||||
{
|
||||
uint8_t c = 0;
|
||||
size_t i = 0;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
u16 s = a[i] + b[i] + c;
|
||||
|
||||
c = (uint8_t) (s >> 8);
|
||||
r[i] = (uint8_t) s;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
int hdcpVerify_ArrayCMP(const uint8_t *a, const uint8_t *b, size_t n)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = n; i > 0; i--) {
|
||||
if (a[i - 1] > b[i - 1])
|
||||
return 1;
|
||||
else if (a[i - 1] < b[i - 1])
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hdcpVerify_ArrayCPY(uint8_t *dst, const uint8_t *src, size_t n)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] = src[i];
|
||||
}
|
||||
|
||||
int hdcpVerify_ArrayDIV(uint8_t *r, const uint8_t *D, const uint8_t *d,
|
||||
size_t n)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (r == D || r == d || (!hdcpVerify_ArrayTST(d, 0, n)) == TRUE) {
|
||||
pr_info("invalid input data");
|
||||
return FALSE;
|
||||
}
|
||||
hdcpVerify_ArraySET(&r[n], 0, n);
|
||||
hdcpVerify_ArrayCPY(r, D, n);
|
||||
for (i = n; i > 0; i--) {
|
||||
r[i - 1 + n] = 0;
|
||||
while (hdcpVerify_ArrayCMP(&r[i - 1], d, n) >= 0) {
|
||||
hdcpVerify_ArraySUB(&r[i - 1], &r[i - 1], d, n);
|
||||
r[i - 1 + n] += 1;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int hdcpVerify_ArrayMAC(uint8_t *r, const uint8_t *M, const uint8_t m, size_t n)
|
||||
{
|
||||
u16 c = 0;
|
||||
size_t i = 0;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
u16 p = (M[i] * m) + c + r[i];
|
||||
|
||||
c = p >> 8;
|
||||
r[i] = (uint8_t) p;
|
||||
}
|
||||
return (uint8_t) c;
|
||||
}
|
||||
|
||||
int hdcpVerify_ArrayMUL(uint8_t *r, const uint8_t *M, const uint8_t *m,
|
||||
size_t n)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
if (r == M || r == m) {
|
||||
pr_info("invalid input data");
|
||||
return FALSE;
|
||||
}
|
||||
hdcpVerify_ArraySET(r, 0, n);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (m[i] == 0)
|
||||
continue;
|
||||
else if (m[i] == 1)
|
||||
hdcpVerify_ArrayADD(&r[i], &r[i], M, n - i);
|
||||
else
|
||||
hdcpVerify_ArrayMAC(&r[i], M, m[i], n - i);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void hdcpVerify_ArraySET(uint8_t *dst, const uint8_t src, size_t n)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] = src;
|
||||
}
|
||||
|
||||
int hdcpVerify_ArraySUB(uint8_t *r, const uint8_t *a, const uint8_t *b,
|
||||
size_t n)
|
||||
{
|
||||
uint8_t c = 1;
|
||||
size_t i = 0;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
u16 s = ((uint8_t) a[i] + (uint8_t) (~b[i])) + c;
|
||||
|
||||
c = (uint8_t) (s >> 8);
|
||||
r[i] = (uint8_t) s;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void hdcpVerify_ArraySWP(uint8_t *r, size_t n)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
for (i = 0; i < (n / 2); i++) {
|
||||
uint8_t tmp = r[i];
|
||||
|
||||
r[i] = r[n - 1 - i];
|
||||
r[n - 1 - i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
int hdcpVerify_ArrayTST(const uint8_t *a, const uint8_t b, size_t n)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (a[i] != b)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int hdcpVerify_ComputeEXP(uint8_t *c, const uint8_t *M, const uint8_t *e,
|
||||
const uint8_t *p, size_t n, size_t nE)
|
||||
{
|
||||
int i = 8 * nE - 1;
|
||||
int rc = TRUE;
|
||||
|
||||
/* LR Binary Method */
|
||||
if ((e[i / 8] & (1 << (i % 8))) != 0)
|
||||
hdcpVerify_ArrayCPY(c, M, n);
|
||||
else {
|
||||
hdcpVerify_ArraySET(c, 0, n);
|
||||
c[0] = 1;
|
||||
}
|
||||
for (i -= 1; i >= 0; i--) {
|
||||
rc |= hdcpVerify_ComputeMUL(c, c, c, p, n);
|
||||
if ((e[i / 8] & (1 << (i % 8))) != 0)
|
||||
rc &= hdcpVerify_ComputeMUL(c, c, M, p, n);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int hdcpVerify_ComputeINV(uint8_t *out, const uint8_t *z, const uint8_t *a,
|
||||
size_t n)
|
||||
{
|
||||
uint8_t w[2][SIZE];
|
||||
uint8_t x[2][SIZE];
|
||||
uint8_t y[2][SIZE];
|
||||
uint8_t r[2*SIZE];
|
||||
uint8_t *i, *j, *q, *t;
|
||||
uint8_t *x1, *x2;
|
||||
uint8_t *y1, *y2;
|
||||
|
||||
if ((n > SIZE) || (hdcpVerify_ArrayTST(z, 0, n) == TRUE)
|
||||
|| (hdcpVerify_ArrayTST(a, 0, n) == TRUE)
|
||||
|| (hdcpVerify_ArrayCMP(z, a, n) >= 0)) {
|
||||
pr_info("invalid input data");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hdcpVerify_ArrayCPY(w[0], a, n);
|
||||
hdcpVerify_ArrayCPY(w[1], z, n);
|
||||
i = w[0];
|
||||
j = w[1];
|
||||
|
||||
hdcpVerify_ArraySET(x[1], 0, n);
|
||||
x[1][0] = 1;
|
||||
hdcpVerify_ArraySET(x[0], 0, n);
|
||||
x2 = x[1];
|
||||
x1 = x[0];
|
||||
|
||||
hdcpVerify_ArraySET(y[1], 0, n);
|
||||
hdcpVerify_ArraySET(y[0], 0, n);
|
||||
y[0][0] = 1;
|
||||
y2 = y[1];
|
||||
y1 = y[0];
|
||||
|
||||
do {
|
||||
hdcpVerify_ArrayDIV(r, i, j, n);
|
||||
hdcpVerify_ArrayCPY(i, r, n);
|
||||
q = &r[n];
|
||||
t = i; /* swap i <-> j */
|
||||
i = j;
|
||||
j = t;
|
||||
|
||||
hdcpVerify_ArrayMUL(r, x1, q, n);
|
||||
hdcpVerify_ArraySUB(x2, x2, r, n);
|
||||
t = x2; /* swap x1 <-> x2 */
|
||||
x2 = x1;
|
||||
x1 = t;
|
||||
|
||||
hdcpVerify_ArrayMUL(r, y1, q, n);
|
||||
hdcpVerify_ArraySUB(y2, y2, r, n);
|
||||
t = y2; /* swap y1 <-> y2 */
|
||||
y2 = y1;
|
||||
y1 = t;
|
||||
|
||||
} while (hdcpVerify_ArrayTST(j, 0, n) == FALSE);
|
||||
|
||||
j[0] = 1;
|
||||
if (hdcpVerify_ArrayCMP(i, j, n) != 0) {
|
||||
pr_info("i != 1");
|
||||
return FALSE;
|
||||
}
|
||||
hdcpVerify_ArrayCPY(out, y2, n);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int hdcpVerify_ComputeMOD(uint8_t *dst, const uint8_t *src, const uint8_t *p,
|
||||
size_t n)
|
||||
{
|
||||
uint8_t aux[KSIZE];
|
||||
uint8_t ext[SIZE + 1];
|
||||
uint8_t tmp[2 * (KSIZE + 1)];
|
||||
int i = 0;
|
||||
|
||||
if (n > SIZE) {
|
||||
pr_info("invalid input data");
|
||||
return FALSE;
|
||||
}
|
||||
hdcpVerify_ArrayCPY(aux, src, sizeof(aux));
|
||||
/* TODO: remove extension */
|
||||
hdcpVerify_ArrayCPY(ext, p, n);
|
||||
ext[n] = 0;
|
||||
for (i = sizeof(aux)-n-1; i >= 0; i--) {
|
||||
hdcpVerify_ArrayDIV(tmp, &aux[i], ext, n+1);
|
||||
hdcpVerify_ArrayCPY(&aux[i], tmp, n+1);
|
||||
}
|
||||
hdcpVerify_ArrayCPY(dst, aux, n);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int hdcpVerify_ComputeMUL(uint8_t *p, const uint8_t *a, const uint8_t *b,
|
||||
const uint8_t *m, size_t n)
|
||||
{
|
||||
uint8_t aux[2 * KSIZE + 1];
|
||||
uint8_t ext[KSIZE + 1];
|
||||
uint8_t tmp[2 * (KSIZE + 1)];
|
||||
size_t i = 0;
|
||||
int j = 0;
|
||||
|
||||
if (n > KSIZE) {
|
||||
pr_info("invalid input data");
|
||||
return FALSE;
|
||||
}
|
||||
hdcpVerify_ArraySET(aux, 0, sizeof(aux));
|
||||
for (i = 0; i < n; i++) {
|
||||
/* TODO: extension was faster */
|
||||
aux[n+i] = hdcpVerify_ArrayMAC(&aux[i], a, b[i], n);
|
||||
}
|
||||
/* TODO: reuse ComputeMOD */
|
||||
hdcpVerify_ArrayCPY(ext, m, n);
|
||||
ext[n] = 0;
|
||||
for (j = n; j >= 0; j--) {
|
||||
hdcpVerify_ArrayDIV(tmp, &aux[j], ext, n+1);
|
||||
hdcpVerify_ArrayCPY(&aux[j], tmp, n+1);
|
||||
}
|
||||
hdcpVerify_ArrayCPY(p, aux, n);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int hdcpVerify_KSV(const uint8_t *data, size_t size)
|
||||
{
|
||||
size_t i = 0;
|
||||
struct sha_t sha;
|
||||
|
||||
if (data == 0 || size < (HEADER + SHAMAX)) {
|
||||
pr_info("invalid input data");
|
||||
return FALSE;
|
||||
}
|
||||
sha_Reset(&sha);
|
||||
sha_Input(&sha, data, size - SHAMAX);
|
||||
if (sha_Result(&sha) == FALSE) {
|
||||
pr_info("cannot process SHA digest");
|
||||
return FALSE;
|
||||
}
|
||||
for (i = 0; i < SHAMAX; i++) {
|
||||
if (data[size - SHAMAX + i] != (uint8_t) (sha.mDigest[i / 4]
|
||||
>> ((i % 4) * 8))) {
|
||||
pr_info("SHA digest does not match");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int hdcpVerify_SRM(const uint8_t *data, size_t size)
|
||||
{
|
||||
if (data == 0 || size < (VRL_HEADER + VRL_NUMBER + 2 * DSAMAX)) {
|
||||
pr_info("invalid input data");
|
||||
return FALSE;
|
||||
}
|
||||
/* M, n, r, s */
|
||||
return hdcpVerify_DSA(data, size - 2 * DSAMAX, &data[size - 2 * DSAMAX],
|
||||
&data[size - DSAMAX]);
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HDCPVERIFY_H_
|
||||
#define HDCPVERIFY_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/printk.h>
|
||||
#include "hdcp.h"
|
||||
|
||||
struct sha_t {
|
||||
uint8_t mLength[8];
|
||||
uint8_t mBlock[64];
|
||||
int mIndex;
|
||||
int mComputed;
|
||||
int mCorrupted;
|
||||
unsigned int mDigest[5];
|
||||
};
|
||||
|
||||
#define KSV_LEN 5
|
||||
#define KSV_MSK 0x7F
|
||||
#define VRL_LENGTH 0x05
|
||||
#define VRL_HEADER 5
|
||||
#define VRL_NUMBER 3
|
||||
#define HEADER 10
|
||||
#define SHAMAX 20
|
||||
#define DSAMAX 20
|
||||
|
||||
void sha_Reset(struct sha_t *sha);
|
||||
|
||||
int sha_Result(struct sha_t *sha);
|
||||
|
||||
void sha_Input(struct sha_t *sha, const uint8_t *data, size_t size);
|
||||
|
||||
void sha_ProcessBlock(struct sha_t *sha);
|
||||
|
||||
void sha_PadMessage(struct sha_t *sha);
|
||||
|
||||
int hdcpVerify_DSA(const uint8_t *M, size_t n, const uint8_t *r,
|
||||
const uint8_t *s);
|
||||
|
||||
int hdcpVerify_ArrayADD(uint8_t *r, const uint8_t *a, const uint8_t *b,
|
||||
size_t n);
|
||||
|
||||
int hdcpVerify_ArrayCMP(const uint8_t *a, const uint8_t *b, size_t n);
|
||||
|
||||
void hdcpVerify_ArrayCPY(uint8_t *dst, const uint8_t *src, size_t n);
|
||||
|
||||
int hdcpVerify_ArrayDIV(uint8_t *r, const uint8_t *D, const uint8_t *d,
|
||||
size_t n);
|
||||
|
||||
int hdcpVerify_ArrayMAC(uint8_t *r, const uint8_t *M, const uint8_t m,
|
||||
size_t n);
|
||||
|
||||
int hdcpVerify_ArrayMUL(uint8_t *r, const uint8_t *M, const uint8_t *m,
|
||||
size_t n);
|
||||
|
||||
void hdcpVerify_ArraySET(uint8_t *dst, const uint8_t src, size_t n);
|
||||
|
||||
int hdcpVerify_ArraySUB(uint8_t *r, const uint8_t *a, const uint8_t *b,
|
||||
size_t n);
|
||||
|
||||
void hdcpVerify_ArraySWP(uint8_t *r, size_t n);
|
||||
|
||||
int hdcpVerify_ArrayTST(const uint8_t *a, const uint8_t b, size_t n);
|
||||
|
||||
int hdcpVerify_ComputeEXP(uint8_t *c, const uint8_t *M, const uint8_t *e,
|
||||
const uint8_t *p, size_t n, size_t nE);
|
||||
|
||||
int hdcpVerify_ComputeINV(uint8_t *out, const uint8_t *z, const uint8_t *a,
|
||||
size_t n);
|
||||
|
||||
int hdcpVerify_ComputeMOD(uint8_t *dst, const uint8_t *src, const uint8_t *p,
|
||||
size_t n);
|
||||
|
||||
int hdcpVerify_ComputeMUL(uint8_t *p, const uint8_t *a, const uint8_t *b,
|
||||
const uint8_t *m, size_t n);
|
||||
|
||||
int hdcpVerify_KSV(const uint8_t *data, size_t size);
|
||||
|
||||
int hdcpVerify_SRM(const uint8_t *data, size_t size);
|
||||
|
||||
#endif /* HDCPVERIFY_H_ */
|
||||
@@ -44,9 +44,9 @@
|
||||
#include "hdmi_tx_reg.h"
|
||||
#include "tvenc_conf.h"
|
||||
#include "common.h"
|
||||
#include "hdcpVerify.h"
|
||||
#include "hw_clk.h"
|
||||
#include <linux/arm-smccc.h>
|
||||
#include "checksha.h"
|
||||
|
||||
static void mode420_half_horizontal_para(void);
|
||||
static void hdmi_phy_suspend(void);
|
||||
@@ -4192,42 +4192,45 @@ static void hdcp_ksv_sha1_calc(struct hdmitx_dev *hdev)
|
||||
size_t list = 0;
|
||||
size_t size = 0;
|
||||
size_t i = 0;
|
||||
int valid = HDCP_IDLE;
|
||||
int valid = HDCP_NULL;
|
||||
unsigned char ksvs[635] = {0}; /* Max 127 * 5 */
|
||||
int j = 0;
|
||||
|
||||
/* 0x165e: Page 95 */
|
||||
hdcp_mKsvListBuf = kmalloc(0x1660, GFP_ATOMIC);
|
||||
if (hdcp_mKsvListBuf) {
|
||||
/* KSV_LEN; */
|
||||
list = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_0) & KSV_MSK;
|
||||
/* KSV_SIZE; */
|
||||
list = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_0) & KSV_MASK;
|
||||
if (list <= HDCP_NMOOFDEVICES) {
|
||||
size = (list * KSV_LEN) + HEADER + SHAMAX;
|
||||
size = (list * KSV_SIZE) + HDCP_HEAD + SHA_MAX_SIZE;
|
||||
for (i = 0; i < size; i++) {
|
||||
if (i < HEADER) { /* BSTATUS & M0 */
|
||||
hdcp_mKsvListBuf[(list * KSV_LEN) + i]
|
||||
if (i < HDCP_HEAD) { /* BSTATUS & M0 */
|
||||
hdcp_mKsvListBuf[(list * KSV_SIZE) + i]
|
||||
= hdmitx_rd_reg(
|
||||
HDMITX_DWC_HDCP_BSTATUS_0 + i);
|
||||
} else if (i < (HEADER + (list * KSV_LEN))) {
|
||||
} else if (i < (HDCP_HEAD +
|
||||
(list * KSV_SIZE))) {
|
||||
/* KSV list */
|
||||
hdcp_mKsvListBuf[i - HEADER] =
|
||||
hdcp_mKsvListBuf[i - HDCP_HEAD] =
|
||||
hdmitx_rd_reg(
|
||||
HDMITX_DWC_HDCP_BSTATUS_0 + i);
|
||||
ksvs[j] = hdcp_mKsvListBuf[i - HEADER];
|
||||
ksvs[j] =
|
||||
hdcp_mKsvListBuf[i - HDCP_HEAD];
|
||||
j++;
|
||||
} else { /* SHA */
|
||||
hdcp_mKsvListBuf[i] = hdmitx_rd_reg(
|
||||
HDMITX_DWC_HDCP_BSTATUS_0 + i);
|
||||
}
|
||||
}
|
||||
valid = hdcpVerify_KSV(hdcp_mKsvListBuf, size)
|
||||
== TRUE ? HDCP_KSV_LIST_READY :
|
||||
HDCP_ERR_KSV_LIST_NOT_VALID;
|
||||
if (calc_hdcp_ksv_valid(hdcp_mKsvListBuf, size) == TRUE)
|
||||
valid = HDCP_KSVLIST_VALID;
|
||||
else
|
||||
valid = HDCP_KSVLIST_INVALID;
|
||||
}
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 0, 1);
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL,
|
||||
(valid == HDCP_KSV_LIST_READY) ? 0 : 1, 3, 1);
|
||||
if (valid == HDCP_KSV_LIST_READY)
|
||||
(valid == HDCP_KSVLIST_VALID) ? 0 : 1, 3, 1);
|
||||
if (valid == HDCP_KSVLIST_VALID)
|
||||
hdcp_ksv_store(ksvs, j);
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 1, 2, 1);
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 2, 1);
|
||||
|
||||
Reference in New Issue
Block a user