662 lines
13 KiB
C
662 lines
13 KiB
C
|
/*
|
||
|
* drivers/soc/samsung/exynos-hdcp/exynos-hdcp2-selftest.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 <linux/slab.h>
|
||
|
#include <linux/module.h>
|
||
|
#include <asm/cacheflush.h>
|
||
|
|
||
|
#include "../exynos-hdcp2-config.h"
|
||
|
#include "../exynos-hdcp2-protocol-msg.h"
|
||
|
#if defined(CONFIG_HDCP2_EMULATION_MODE)
|
||
|
#include "../exynos-hdcp2-testvector.h"
|
||
|
#endif
|
||
|
#include "../exynos-hdcp2-misc.h"
|
||
|
#include "../exynos-hdcp2-encrypt.h"
|
||
|
#include "../exynos-hdcp2.h"
|
||
|
#include "../exynos-hdcp2-log.h"
|
||
|
|
||
|
#define AKE_INIT_LEN 9
|
||
|
#define AKE_TRANSMITTER_INFO_LEN 6
|
||
|
#define AKE_NO_STORED_KM_LEN 129
|
||
|
#define AKE_STORED_KM_LEN 33
|
||
|
#define AKE_SEND_PAIRING_INFO_LEN 17
|
||
|
#define LC_INIT_LEN 9
|
||
|
#define LC_RTT_CHALLENGE_LEN 17
|
||
|
#define SKE_SEND_EKS_LEN 25
|
||
|
|
||
|
struct hdcp_tx_ctx uc_tx_ctx;
|
||
|
struct hdcp_rx_ctx uc_rx_ctx;
|
||
|
|
||
|
/* Test HDCP Encryption */
|
||
|
static int utc_encryption(struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
uint8_t *input = NULL;
|
||
|
u64 input_phy = 0;
|
||
|
uint8_t *output = NULL;
|
||
|
u64 output_phy = 0;
|
||
|
int ret = 0;
|
||
|
size_t packet_len;
|
||
|
uint8_t pes_priv[HDCP_PRIVATE_DATA_LEN];
|
||
|
|
||
|
packet_len = sizeof(tv_plain);
|
||
|
|
||
|
/* Allocate enc in/out buffer for test */
|
||
|
input = (uint8_t *)kzalloc(packet_len, GFP_KERNEL);
|
||
|
if (!input) {
|
||
|
hdcp_err("alloc enc input buffer is failed\n");
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
|
||
|
output = (uint8_t *)kzalloc(packet_len, GFP_KERNEL);
|
||
|
if (!output) {
|
||
|
kfree(input);
|
||
|
hdcp_err("alloc enc input buffer is failed\n");
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
|
||
|
/* send physical address to SWd */
|
||
|
input_phy = virt_to_phys((void *)input);
|
||
|
output_phy = virt_to_phys((void *)output);
|
||
|
|
||
|
/* set input param */
|
||
|
memcpy(input, tv_plain, packet_len);
|
||
|
/* set input counters */
|
||
|
memset(&tx_ctx->input_ctr, 0x00, HDCP_INPUT_CTR_LEN);
|
||
|
/* set output counters */
|
||
|
memset(&tx_ctx->str_ctr, 0x00, HDCP_STR_CTR_LEN);
|
||
|
|
||
|
// mark on 5.4
|
||
|
// __flush_dcache_area(input, packet_len);
|
||
|
// __flush_dcache_area(output, packet_len);
|
||
|
|
||
|
ret = encrypt_packet(pes_priv,
|
||
|
input_phy, packet_len,
|
||
|
output_phy, packet_len,
|
||
|
tx_ctx);
|
||
|
if (ret) {
|
||
|
kfree(input);
|
||
|
kfree(output);
|
||
|
hdcp_err("encrypt_packet() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (memcmp(output, tv_cipher, packet_len)) {
|
||
|
hdcp_err("Wrong encrypted value.\n");
|
||
|
hdcp_err("expected:\n");
|
||
|
hdcp_hexdump(tv_cipher, packet_len);
|
||
|
|
||
|
hdcp_err("actual:\n");
|
||
|
hdcp_hexdump(output, packet_len);
|
||
|
|
||
|
kfree(input);
|
||
|
kfree(output);
|
||
|
return -1;
|
||
|
} else
|
||
|
hdcp_info("HDCP:Encryption success.\n");
|
||
|
|
||
|
kfree(input);
|
||
|
kfree(output);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_ske_send_eks(struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
uint8_t m[525];
|
||
|
size_t m_len;
|
||
|
int ret;
|
||
|
int i;
|
||
|
|
||
|
tx_ctx->share_skey = 0;
|
||
|
|
||
|
ret = cap_protocol_msg(SKE_SEND_EKS, m, &m_len, tx_ctx, rx_ctx);
|
||
|
if (ret) {
|
||
|
hdcp_err("SKE_Send_Eks() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* check message ID & length */
|
||
|
if (m[0] != 11) {
|
||
|
hdcp_err("Message ID ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (m_len != SKE_SEND_EKS_LEN) {
|
||
|
hdcp_err("Message LENGTH ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* compare encrypted session key with test vector */
|
||
|
for (i = 0; i < HDCP_AKE_MKEY_BYTE_LEN; i++)
|
||
|
if (tv_eskey[i] != m[1+i])
|
||
|
break;
|
||
|
|
||
|
if (i != HDCP_AKE_MKEY_BYTE_LEN) {
|
||
|
hdcp_err("m doesn't match (%dth)\n", i);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Test SKE APIs */
|
||
|
static int utc_ske(struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx, int *cnt, int *fail)
|
||
|
{
|
||
|
return utc_ske_send_eks(tx_ctx, rx_ctx);
|
||
|
}
|
||
|
|
||
|
static int utc_lc_send_l_prime(struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = decap_protocol_msg(LC_SEND_L_PRIME, msg_rx_lc_send_l_prime,
|
||
|
sizeof(msg_rx_send_h_prime),
|
||
|
tx_ctx, rx_ctx);
|
||
|
if (ret) {
|
||
|
hdcp_err("LC_Send_L_prime() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_rtt_challenge(struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
uint8_t m[525];
|
||
|
size_t m_len;
|
||
|
int ret;
|
||
|
int i;
|
||
|
|
||
|
ret = cap_protocol_msg(RTT_CHALLENGE, m, &m_len, tx_ctx, rx_ctx);
|
||
|
if (ret) {
|
||
|
hdcp_err("RTT_Challenge() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* check message ID & length */
|
||
|
if (m[0] != 14) {
|
||
|
hdcp_err("Message ID ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (m_len != LC_RTT_CHALLENGE_LEN) {
|
||
|
hdcp_err("Message LENGTH ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* check ls128_hmac */
|
||
|
for (i = 0; i < HDCP_HMAC_SHA256_LEN/2; i++)
|
||
|
if (m[i+1] != tv_lc_lsb16_hmac[i])
|
||
|
break;
|
||
|
|
||
|
if (i != HDCP_HMAC_SHA256_LEN/2) {
|
||
|
hdcp_err("failed to compare ls128 hmac\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_rtt_ready(struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = decap_protocol_msg(RTT_READY, msg_rx_rtt_ready,
|
||
|
sizeof(msg_rx_rtt_ready),
|
||
|
tx_ctx,
|
||
|
rx_ctx);
|
||
|
if (ret) {
|
||
|
hdcp_err("RTT_Ready() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_lc_init(struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
uint8_t m[525];
|
||
|
size_t m_len;
|
||
|
int ret;
|
||
|
int i;
|
||
|
|
||
|
ret = cap_protocol_msg(LC_INIT, m, &m_len, tx_ctx, rx_ctx);
|
||
|
if (ret) {
|
||
|
hdcp_err("LC_Init() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* check message ID & length */
|
||
|
if (m[0] != 9) {
|
||
|
hdcp_err("Message ID ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (m_len != LC_INIT_LEN) {
|
||
|
hdcp_err("Message LENGTH ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if ((rx_ctx->version != HDCP_VERSION_2_0)
|
||
|
&& tx_ctx->lc_precomp
|
||
|
&& rx_ctx->lc_precomp) {
|
||
|
for (i = 0; i < HDCP_HMAC_SHA256_LEN/2; i++)
|
||
|
if (tx_ctx->lsb16_hmac[i] != tv_lc_hmac[i+16])
|
||
|
break;
|
||
|
if (i != HDCP_HMAC_SHA256_LEN/2) {
|
||
|
hdcp_err("failed to compare lsb16 hmac\n");
|
||
|
return -1;
|
||
|
}
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Test LC APIs */
|
||
|
static int utc_lc(struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx,
|
||
|
int *cnt, int *fail)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = utc_lc_init(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
ret = utc_lc_send_l_prime(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
ret = utc_rtt_ready(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
ret = utc_rtt_challenge(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_ake_send_h_prime(struct hdcp_tx_ctx *tx_ctx,
|
||
|
struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = decap_protocol_msg(AKE_SEND_H_PRIME, msg_rx_send_h_prime,
|
||
|
sizeof(msg_rx_send_h_prime),
|
||
|
tx_ctx, rx_ctx);
|
||
|
if (ret) {
|
||
|
hdcp_err("AKE_Send_H_prime() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_ake_send_rrx(struct hdcp_tx_ctx *tx_ctx,
|
||
|
struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
int ret;
|
||
|
int i;
|
||
|
|
||
|
ret = decap_protocol_msg(AKE_SEND_RRX, msg_rx_send_rrx, sizeof(msg_rx_send_rrx),
|
||
|
tx_ctx, rx_ctx);
|
||
|
if (ret) {
|
||
|
hdcp_err("make_AKE_Send_rrx() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* compare rrx with test vector */
|
||
|
for (i = 0; i < HDCP_RRX_BYTE_LEN; i++)
|
||
|
if (rx_ctx->rrx[i] != tv_rrx[i])
|
||
|
break;
|
||
|
|
||
|
if (i != HDCP_RRX_BYTE_LEN) {
|
||
|
hdcp_err("rrx doesn't match (%dth)\n", i);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_ake_stored_km(struct hdcp_tx_ctx *tx_ctx,
|
||
|
struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
uint8_t m[525];
|
||
|
size_t m_len;
|
||
|
int ret;
|
||
|
int i;
|
||
|
|
||
|
ret = cap_protocol_msg(AKE_STORED_KM, m, &m_len, tx_ctx, rx_ctx);
|
||
|
if (ret) {
|
||
|
hdcp_err("AKE_Stored_km() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (m[0] != 5) {
|
||
|
hdcp_err("Message ID ERROR, it has %d\n", m[0]);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (m_len != AKE_STORED_KM_LEN) {
|
||
|
hdcp_err("Message LENGTH ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
for (i = 0; i < HDCP_AKE_MKEY_BYTE_LEN; i++)
|
||
|
if (tv_pairing_ekh[i] != m[i+1])
|
||
|
break;
|
||
|
|
||
|
if (i != HDCP_AKE_MKEY_BYTE_LEN) {
|
||
|
hdcp_err("ekh(m) doesn't match (%dth)\n", i);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
for (i = 0; i < HDCP_AKE_MKEY_BYTE_LEN; i++)
|
||
|
if (tv_pairing_m[i] != m[i + 1 + HDCP_AKE_MKEY_BYTE_LEN])
|
||
|
break;
|
||
|
|
||
|
if (i != HDCP_AKE_MKEY_BYTE_LEN) {
|
||
|
hdcp_err("m doesn't match (%dth)\n", i);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_ake_send_pairing_info(struct hdcp_tx_ctx *tx_ctx,
|
||
|
struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
int ret;
|
||
|
int i;
|
||
|
int found_km;
|
||
|
|
||
|
/* Extract Receiver ID */
|
||
|
for (i = 0; i < RECEIVER_ID_BYTE_LEN; i++)
|
||
|
rx_ctx->receiver_id[i] = rx_ctx->cert[i];
|
||
|
|
||
|
ret = decap_protocol_msg(AKE_SEND_PAIRING_INFO, msg_rx_send_pairing_info,
|
||
|
sizeof(msg_rx_send_pairing_info),
|
||
|
tx_ctx, rx_ctx);
|
||
|
if (ret) {
|
||
|
hdcp_err("AKE_SEND_PAIRING_INFO() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
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) {
|
||
|
hdcp_err("find_masterkey() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (found_km) {
|
||
|
for (i = 0; i < HDCP_AKE_MKEY_BYTE_LEN; i++)
|
||
|
if (tx_ctx->ekh_mkey[i] != msg_rx_send_pairing_info[i + 1])
|
||
|
break;
|
||
|
|
||
|
if (i != HDCP_AKE_MKEY_BYTE_LEN) {
|
||
|
hdcp_err("ekh(m) doesn't match (%dth)\n", i);
|
||
|
return -1;
|
||
|
}
|
||
|
} else {
|
||
|
hdcp_err("ekh(m) is not found\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_ake_no_stored_km(struct hdcp_tx_ctx *tx_ctx,
|
||
|
struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
uint8_t m[525];
|
||
|
size_t m_len;
|
||
|
int ret;
|
||
|
int i;
|
||
|
|
||
|
memcpy(rx_ctx->cert, cert, HDCP_RX_CERT_LEN);
|
||
|
|
||
|
ret = cap_protocol_msg(AKE_NO_STORED_KM, m, &m_len, tx_ctx, rx_ctx);
|
||
|
if (ret) {
|
||
|
hdcp_err("make_AKE_No_Stored_km() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (m[0] != 4) {
|
||
|
hdcp_err("Message ID ERROR, it has %d\n", m[0]);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (m_len != AKE_NO_STORED_KM_LEN) {
|
||
|
hdcp_err("Message LENGTH ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
for (i = 0; i < 128; i++)
|
||
|
if (m[i + 1] != tv_emkey[i])
|
||
|
break;
|
||
|
|
||
|
if (i != 128) {
|
||
|
hdcp_err("Encryption Master Key ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_ake_receiver_info(struct hdcp_tx_ctx *tx_ctx,
|
||
|
struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = decap_protocol_msg(AKE_RECEIVER_INFO,
|
||
|
msg_rx_receiver_info,
|
||
|
sizeof(msg_rx_receiver_info),
|
||
|
tx_ctx, rx_ctx);
|
||
|
if (ret) {
|
||
|
hdcp_err("get_Receiver_Info() is failed with %x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_ake_send_cert(struct hdcp_tx_ctx *tx_ctx,
|
||
|
struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = decap_protocol_msg(AKE_SEND_CERT, msg_rx_send_cert,
|
||
|
sizeof(msg_rx_send_cert),
|
||
|
tx_ctx, rx_ctx);
|
||
|
if (ret) {
|
||
|
hdcp_err("get_AKE_Send_Cert() is failed with ret, 0x%x\n",
|
||
|
ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_ake_transmitter_info(struct hdcp_tx_ctx *tx_ctx,
|
||
|
struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
uint8_t m[525];
|
||
|
size_t m_len;
|
||
|
int ret;
|
||
|
|
||
|
ret = cap_protocol_msg(AKE_TRANSMITTER_INFO, m, &m_len, tx_ctx, NULL);
|
||
|
if (ret) {
|
||
|
hdcp_err("cap_ake_transmitter_info() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* check message ID & length */
|
||
|
if (m[0] != 19) {
|
||
|
hdcp_err("Message ID ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if ((m_len != AKE_TRANSMITTER_INFO_LEN) || (m[2] < 6)) {
|
||
|
hdcp_err("Message LENGTH ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* Version & Precompuation Check */
|
||
|
#ifdef HDCP_TX_VERSION_2_1
|
||
|
if (m[3] != HDCP_VERSION_2_1) {
|
||
|
#else
|
||
|
if (m[3] == HDCP_VERSION_2_1) {
|
||
|
#endif
|
||
|
hdcp_err("Version set wrong\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* precomputation check */
|
||
|
#ifdef HDCP_TX_LC_PRECOMPUTE_SUPPORT
|
||
|
if ((m[4] != 0) || (m[5] != 0x01)) {
|
||
|
#else
|
||
|
if ((m[4] != 0) || (m[5] != 0)) {
|
||
|
#endif
|
||
|
hdcp_err("Precomputation ERROR, it has 0x%x%x\n", m[4], m[5]);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int utc_ake_init(struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx)
|
||
|
{
|
||
|
uint8_t m[525];
|
||
|
size_t m_len;
|
||
|
int ret;
|
||
|
|
||
|
ret = cap_protocol_msg(AKE_INIT, m, &m_len, tx_ctx, NULL);
|
||
|
if (ret) {
|
||
|
hdcp_err("cap_ake_init() is failed with 0x%x\n", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* check message ID & length */
|
||
|
if (m[0] != 2) {
|
||
|
hdcp_err("Message ID ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (m_len != AKE_INIT_LEN) {
|
||
|
hdcp_err("Message LENGTH ERROR\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Test AKE APIs */
|
||
|
static int utc_ake(struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx,
|
||
|
int *cnt, int *fail)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = utc_ake_init(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
ret = utc_ake_transmitter_info(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
ret = utc_ake_send_cert(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
ret = utc_ake_receiver_info(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
ret = utc_ake_no_stored_km(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
ret = utc_ake_send_rrx(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
ret = utc_ake_send_h_prime(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
ret = utc_ake_send_pairing_info(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
ret = utc_ake_stored_km(tx_ctx, rx_ctx);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Test HDCP API functions */
|
||
|
int iia_hdcp_protocol_self_test(void)
|
||
|
{
|
||
|
int ake_cnt = 0, ake_fail = 0;
|
||
|
int lc_cnt = 0, lc_fail = 0;
|
||
|
int ske_cnt = 0, ske_fail = 0;
|
||
|
int ret;
|
||
|
|
||
|
hdcp_info("[ AKE UTC]\n");
|
||
|
ret = utc_ake(&uc_tx_ctx, &uc_rx_ctx, &ake_cnt, &ake_fail);
|
||
|
if (ret < 0) {
|
||
|
hdcp_info("AKE UTC: fail\n");
|
||
|
return ret;
|
||
|
} else {
|
||
|
hdcp_info("AKE UTC: success\n");
|
||
|
}
|
||
|
|
||
|
hdcp_info("\n[ LC UTC]\n");
|
||
|
ret = utc_lc(&uc_tx_ctx, &uc_rx_ctx, &lc_cnt, &lc_fail);
|
||
|
if (ret < 0) {
|
||
|
hdcp_info("LC UTC: fail\n");
|
||
|
return ret;
|
||
|
} else {
|
||
|
hdcp_info("LC UTC: success\n");
|
||
|
}
|
||
|
|
||
|
hdcp_info("\n[ SKE UTC]\n");
|
||
|
ret = utc_ske(&uc_tx_ctx, &uc_rx_ctx, &ske_cnt, &ske_fail);
|
||
|
if (ret < 0) {
|
||
|
hdcp_info("SKE UTC: fail\n");
|
||
|
return ret;
|
||
|
} else {
|
||
|
hdcp_info("SKE UTC: success\n");
|
||
|
}
|
||
|
|
||
|
hdcp_info("\n[ Encryption UTC]\n");
|
||
|
ret = utc_encryption(&uc_tx_ctx, &uc_rx_ctx);
|
||
|
if (ret < 0) {
|
||
|
hdcp_info("Encrypt UTC: fail\n");
|
||
|
return ret;
|
||
|
} else {
|
||
|
hdcp_info("Encrypt UTC: success\n");
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
MODULE_LICENSE("GPL");
|