From ee2c15ae28386238c06ab90ec013e7c184bd7a55 Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Wed, 5 Sep 2018 17:12:53 +0800 Subject: [PATCH] hdmitx: adjust hdmitx related code [1/2] PD#173252: hdmitx: adjust hdmitx related code Change-Id: Ie8dfd4b21055b9ab34b50efca65dfafa78f2254d Signed-off-by: Zongdong Jiao --- MAINTAINERS | 2 +- .../media/vout/hdmitx/hdmi_tx_20/hw/Makefile | 2 +- .../vout/hdmitx/hdmi_tx_20/hw/checksha.c | 200 ++++++ .../vout/hdmitx/hdmi_tx_20/hw/checksha.h | 59 ++ .../media/vout/hdmitx/hdmi_tx_20/hw/hdcp.h | 45 -- .../vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.c | 600 ------------------ .../vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.h | 97 --- .../vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c | 33 +- 8 files changed, 279 insertions(+), 759 deletions(-) create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.h delete mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcp.h delete mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.c delete mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.h diff --git a/MAINTAINERS b/MAINTAINERS index e3b8fc363d18..941872eb177c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13538,9 +13538,9 @@ M: Tao Zeng F: arch/arm/mach-meson/Makefile.boot HDMITX OUTPUT DRIVER -M: Zongdong Jiao M: Yi Zhou M: Kaifu Hu +M: Zongdong Jiao S: Maintained F: drivers/amlogic/media/vout/hdmitx/* F: drivers/amlogic/media/vout/hdmitx/hdcp/* diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/Makefile b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/Makefile index c7d7ff34f4ae..9c61c2e575c3 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/Makefile +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/Makefile @@ -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 diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.c new file mode 100644 index 000000000000..ca289be18981 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.c @@ -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 +#include +#include +#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; +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.h new file mode 100644 index 000000000000..f4cd9c0c3567 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/checksha.h @@ -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__ */ diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcp.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcp.h deleted file mode 100644 index 5fe69afde3a1..000000000000 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcp.h +++ /dev/null @@ -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_ */ diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.c deleted file mode 100644 index ebe66fd8f70d..000000000000 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.c +++ /dev/null @@ -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]); -} - diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.h deleted file mode 100644 index 404074b1c3e3..000000000000 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.h +++ /dev/null @@ -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 -#include -#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_ */ diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index ec219c1e158a..e8a5a72dbbc0 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -44,9 +44,9 @@ #include "hdmi_tx_reg.h" #include "tvenc_conf.h" #include "common.h" -#include "hdcpVerify.h" #include "hw_clk.h" #include +#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);