/* * drivers/soc/samsung/exynos-hdcp/exynos-hdcp2-protocol-msg.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 #include "exynos-hdcp2-config.h" #include "exynos-hdcp2-protocol-msg.h" #include "exynos-hdcp2-teeif.h" #include "exynos-hdcp2.h" #include "exynos-hdcp2-log.h" #include "exynos-hdcp2-misc.h" #include "dp_link/exynos-hdcp2-dplink-protocol-msg.h" /* HDCP protocol message capulate & decapulate functions for IIA */ static int cap_ake_init(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int cap_ake_transmitter_info(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int cap_ake_no_stored_km(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int cap_ake_stored_km(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int decap_ake_send_cert(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int decap_ake_receiver_info(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int decap_ake_send_rrx(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int decap_ake_send_h_prime(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int decap_ake_send_pairing_info(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int cap_lc_init(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int cap_rtt_challenge(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int decap_lc_send_l_prime(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int decap_rtt_ready(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int cap_ske_send_eks(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int decap_RepeaterAuth_send_ReceiverID_List(uint8_t *m,size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int cap_RepeaterAuth_Send_Ack(uint8_t *m,size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int decap_Receiver_AuthStatus(uint8_t *m,size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int cap_RepeaterAuth_Stream_Manage(uint8_t *m,size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); static int decap_RepeaterAuth_Stream_Ready(uint8_t *m,size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx); int (*proto_iia[])(uint8_t *, size_t *, struct hdcp_tx_ctx *, struct hdcp_rx_ctx *) = { cap_ake_init, decap_ake_send_cert, cap_ake_no_stored_km, cap_ake_stored_km, decap_ake_send_rrx, decap_ake_send_h_prime, decap_ake_send_pairing_info, cap_lc_init, decap_lc_send_l_prime, cap_ske_send_eks, decap_RepeaterAuth_send_ReceiverID_List, decap_rtt_ready, cap_rtt_challenge, cap_RepeaterAuth_Send_Ack, cap_RepeaterAuth_Stream_Manage, decap_RepeaterAuth_Stream_Ready, decap_Receiver_AuthStatus, cap_ake_transmitter_info, decap_ake_receiver_info, }; /* HDCP protocol message capulate & decapulate functions for DP_LINK */ extern int (*proto_dp[])(uint8_t *, size_t *, struct hdcp_tx_ctx *, struct hdcp_rx_ctx *); int ske_generate_sessionkey(uint32_t lk_type, uint8_t *enc_skey, int share_skey) { int ret; ret = teei_generate_skey(lk_type, enc_skey, HDCP_SKE_SKEY_LEN, share_skey); if (ret) { hdcp_err("generate_session_key() is failed with %x\n", ret); return ERR_GENERATE_SESSION_KEY; } return 0; } int ske_generate_riv(uint8_t *out) { int ret; ret = teei_generate_riv(out, HDCP_RTX_BYTE_LEN); if (ret) { hdcp_err("teei_generate_riv() is failed with %x\n", ret); return ERR_GENERATE_NON_SECKEY; } return 0; } int lc_generate_rn(uint8_t *out, size_t out_len) { int ret; ret = teei_gen_rn(out, out_len); if (ret) { hdcp_err("lc_generate_rn() is failed with %x\n", ret); return ERR_GENERATE_NON_SECKEY; } return 0; } int lc_make_hmac(struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx, uint32_t lk_type) { int ret; if ((rx_ctx->version != HDCP_VERSION_2_0) && tx_ctx->lc_precomp && rx_ctx->lc_precomp) { ret = teei_gen_lc_hmac(lk_type, tx_ctx->lsb16_hmac); if (ret) { hdcp_err("compute_lc_whmac() is failed with %x\n", ret); return ERR_COMPUTE_LC_HMAC; } } else { hdcp_err("LC precomp is not supported\n"); return ERR_COMPUTE_LC_HMAC; } return ret; } int lc_compare_hmac(uint8_t *rx_hmac, size_t hmac_len) { int ret; ret = teei_compare_lc_hmac(rx_hmac, hmac_len); if (ret) { hdcp_err("compare_lc_hmac_val() is failed with %x\n", ret); return ERR_COMPARE_LC_HMAC; } return ret; } static int ake_generate_rtx(uint32_t lk_type, uint8_t *out, size_t out_len) { int ret; /* IIA Spec does not use TxCaps */ ret = teei_gen_rtx(lk_type, out, out_len, NULL, 0); if (ret) { hdcp_err("generate rtx is failed with 0x%x\n", ret); return ERR_GENERATE_NON_SECKEY; } return 0; } static int ake_set_tx_info(struct hdcp_tx_ctx *tx_ctx) { int ret; uint8_t version[HDCP_VERSION_LEN]; uint8_t caps_mask[HDCP_CAPABILITY_MASK_LEN]; /* Init Version & Precomputation */ ret = teei_get_txinfo(version, HDCP_VERSION_LEN, caps_mask, HDCP_CAPABILITY_MASK_LEN); if (ret) { hdcp_err("Get Tx info is failed with 0x%x\n", ret); return ERR_GET_TX_INFO; } hdcp_debug("Tx: version(0x%02x) Caps_maks(0x%02x%02x)\n", version[0], caps_mask[0], caps_mask[1]); tx_ctx->version = version[0]; tx_ctx->lc_precomp = caps_mask[1]; /* todo: check seq_num_M init position*/ tx_ctx->seq_num_M = 0; return 0; } static int ake_set_rx_info(struct hdcp_rx_ctx *rx_ctx) { int ret; uint8_t version[HDCP_VERSION_LEN]; uint8_t caps_mask[HDCP_CAPABILITY_MASK_LEN]; version[0] = rx_ctx->version; caps_mask[0] = 0x00; /* reserved field in IIA spec */ caps_mask[1] = rx_ctx->lc_precomp; /* Init Version & Precomputation */ ret = teei_set_rxinfo(version, HDCP_VERSION_LEN, caps_mask, HDCP_CAPABILITY_MASK_LEN); if (ret) { hdcp_err("Get Tx info is failed with 0x%x\n", ret); return ERR_SET_RX_INFO; } return 0; } static int ake_set_rrx(uint8_t *rrx, size_t rrx_len) { int ret; /* set Rrx value */ ret = teei_set_rrx(rrx, rrx_len); if (ret) { hdcp_err("set rrx is failed with 0x%x\n", ret); return ERR_SET_RRX; } return 0; } int ake_verify_cert(uint8_t *cert, size_t cert_len, uint8_t *rrx, size_t rrx_len, uint8_t *rx_caps, size_t rx_caps_len) { int ret; ret = teei_verify_cert(cert, cert_len, rrx, rrx_len, rx_caps, rx_caps_len); if (ret) { hdcp_err("teei_verify_cert() is failed with %x\n", ret); return ERR_VERIFY_CERT; } return 0; } int ake_generate_masterkey(uint32_t lk_type, uint8_t *enc_mkey, size_t elen) { int ret; /* Generate Encrypted & Wrapped Master Key */ ret = teei_generate_master_key(lk_type, enc_mkey, elen); if (ret) { hdcp_err("generate_master_key() is failed with %x\n", ret); return ERR_GENERATE_MASTERKEY; } return ret; } int ake_compare_hmac(uint8_t *rx_hmac, size_t rx_hmac_len) { int ret; ret = teei_compare_ake_hmac(rx_hmac, rx_hmac_len); if (ret) { hdcp_err("teei_compare_hmac() is failed with %x\n", ret); return ERR_COMPUTE_AKE_HMAC; } return 0; } int ake_store_master_key(uint8_t *ekh_mkey, size_t ekh_mkey_len) { int ret; ret = teei_set_pairing_info(ekh_mkey, ekh_mkey_len); if (ret) { hdcp_err("teei_store_pairing_info() is failed with %x\n", ret); return ERR_STORE_MASTERKEY; } return 0; } int ake_find_masterkey(int *found_km, uint8_t *ekh_mkey, size_t ekh_mkey_len, uint8_t *m, size_t m_len) { int ret; ret = teei_get_pairing_info(ekh_mkey, ekh_mkey_len, m, m_len); if (ret) { if (ret == E_HDCP_PRO_INVALID_RCV_ID) { hdcp_info("RCV id is not found\n"); *found_km = 0; return 0; } else { *found_km = 0; hdcp_err("teei_store_pairing_info() is failed with %x\n", ret); return ERR_FIND_MASTERKEY; } } *found_km = 1; return 0; } static int cap_ake_init(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { size_t rtx_len; int ret; /* Buffer Check */ if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL)) return ERR_WRONG_BUFFER; rtx_len = HDCP_AKE_RTX_BYTE_LEN; /* Generate rtx */ ret = ake_generate_rtx(HDCP_LINK_TYPE_IIA, tx_ctx->rtx, rtx_len); if (ret) { hdcp_err("failed to generate rtx\n"); return ERR_GENERATE_RTX; } /* Make Message */ m[0] = AKE_INIT; memcpy(&m[1], tx_ctx->rtx, rtx_len); *m_len = 1 + rtx_len; #ifdef HDCP_AKE_DEBUG hdcp_debug("HDCP: cap_ake_init(%lu) \n", *m_len); hdcp_hexdump(m, *m_len); #endif return 0; } static int cap_ake_transmitter_info(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret; if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL)) return ERR_WRONG_BUFFER; /* Set info */ ret = ake_set_tx_info(tx_ctx); if (ret) { hdcp_err("failed to set info\n"); return ERR_SET_INFO; } /* Make Message */ m[0] = AKE_TRANSMITTER_INFO; m[1] = 0x0; m[2] = 0x06; m[3] = tx_ctx->version; m[4] = 0x0; m[5] = tx_ctx->lc_precomp; *m_len = 6; #ifdef HDCP_AKE_DEBUG hdcp_debug("cap_ake_transmitter_info(%lu) \n", *m_len); hdcp_hexdump(m, *m_len); #endif return 0; } static int cap_ake_no_stored_km(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { uint8_t enc_mkey[HDCP_AKE_ENCKEY_BYTE_LEN]; int ret; if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL) || (rx_ctx == NULL)) return ERR_WRONG_BUFFER; /* Verify Certificate */ /* IIA spec does not define rrx and RxCaps with Cert message */ ret = ake_verify_cert(rx_ctx->cert, sizeof(rx_ctx->cert), NULL, 0, &(rx_ctx->repeater), HDCP_RX_CAPS_LEN); if (ret) /* authentication failure & * aborts the authentication protocol */ return ret; /* Generate/Encrypt master key */ ret = ake_generate_masterkey(HDCP_LINK_TYPE_IIA, enc_mkey, sizeof(enc_mkey)); /* Generate/Encrypt master key */ if (ret) return ret; /* Make Message */ m[0] = AKE_NO_STORED_KM; memcpy(&m[1], enc_mkey, HDCP_AKE_ENCKEY_BYTE_LEN); *m_len = 1 + HDCP_AKE_ENCKEY_BYTE_LEN; #ifdef HDCP_AKE_DEBUG hdcp_debug("cap_ake_no_stored_km(%lu)\n", *m_len); hdcp_hexdump(m, *m_len); #endif return 0; } static int cap_ake_stored_km(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret; int found_km; if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL)) return ERR_WRONG_BUFFER; /* Generate/Encrypt master key */ 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 || !found_km) { hdcp_err("find_masterkey() is failed with 0x%x\n", ret); return -1; } /* Make Message */ m[0] = AKE_STORED_KM; memcpy(&m[1], tx_ctx->ekh_mkey, HDCP_AKE_EKH_MKEY_BYTE_LEN); memcpy(&m[1] + HDCP_AKE_EKH_MKEY_BYTE_LEN, tx_ctx->m, HDCP_AKE_M_BYTE_LEN); *m_len = 1 + HDCP_AKE_EKH_MKEY_BYTE_LEN + HDCP_AKE_M_BYTE_LEN; #ifdef HDCP_AKE_DEBUG hdcp_debug("cap_ake_stored_km(%lu) \n", *m_len); hdcp_hexdump(m, *m_len); #endif return 0; } static int decap_ake_send_cert(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret; ret = check_received_msg(m, *m_len, 2 + HDCP_RX_CERT_LEN, AKE_SEND_CERT); if (ret) return ret; rx_ctx->repeater = m[1]; memcpy(rx_ctx->cert, &m[2], HDCP_RX_CERT_LEN); #ifdef HDCP_AKE_DEBUG hdcp_debug("decap_ake_send_cert(%lu) \n", *m_len); hdcp_hexdump(m, *m_len); #endif return 0; } static int decap_ake_receiver_info(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret; ret = check_received_msg(m, *m_len, 6, AKE_RECEIVER_INFO); if (ret) return ret; if ((m[2] < 6) && (m[1] == 0)) { hdcp_err("AKE_Receiver_Info, send wrong length\n"); return ERR_WRONG_MESSAGE_LENGTH; } rx_ctx->version = m[3]; rx_ctx->lc_precomp = m[5]; ret = ake_set_rx_info(rx_ctx); if (ret) { hdcp_err("AKE set rx info failed. ret(0x%x)\n", ret); return ret; } #ifdef HDCP_AKE_DEBUG hdcp_debug("decap_ake_receiver_info()\n"); hdcp_debug("version: 0x%02x\n", rx_ctx->version); hdcp_debug("HDCP lc_precomp: 0x%02x\n", rx_ctx->lc_precomp); #endif return 0; } static int decap_ake_send_rrx(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret; uint8_t rrx[HDCP_RRX_BYTE_LEN] = {0}; ret = check_received_msg(m, *m_len, 1 + HDCP_RRX_BYTE_LEN, AKE_SEND_RRX); if (ret) return ret; memcpy(rx_ctx->rrx, &m[1], HDCP_RRX_BYTE_LEN); memcpy(rrx, &m[1], HDCP_RRX_BYTE_LEN); ret = ake_set_rrx(rrx, HDCP_RRX_BYTE_LEN); if (ret) return ret; #ifdef HDCP_AKE_DEBUG hdcp_debug("decap_ake_send_rrx\n"); hdcp_hexdump(rx_ctx->rrx, HDCP_RRX_BYTE_LEN); #endif return 0; } static int decap_ake_send_h_prime(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret; ret = check_received_msg(m, *m_len, 1 + HDCP_HMAC_SHA256_LEN, AKE_SEND_H_PRIME); if (ret) return ret; /* compare H == H' */ ret = ake_compare_hmac(&m[1], HDCP_HMAC_SHA256_LEN); if (ret) return ret; #ifdef HDCP_AKE_DEBUG hdcp_debug("decap_ake_send_h_prime\n"); hdcp_debug("given hmac:\n"); hdcp_hexdump(&m[1], HDCP_HMAC_SHA256_LEN); #endif return 0; } static int decap_ake_send_pairing_info(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret; ret = check_received_msg(m, *m_len, 1 + HDCP_AKE_EKH_MKEY_BYTE_LEN, AKE_SEND_PAIRING_INFO); if (ret) return ret; memcpy(tx_ctx->ekh_mkey, &m[1], HDCP_AKE_EKH_MKEY_BYTE_LEN); /* Store the Key */ ret = ake_store_master_key(tx_ctx->ekh_mkey, HDCP_AKE_EKH_MKEY_BYTE_LEN); if (ret) return ret; #ifdef HDCP_AKE_DEBUG hdcp_debug("decap_ake_send_pairing_info(%lu)\n", *m_len); hdcp_debug("rx_ctx->ekh_mkey:\n"); hdcp_hexdump(tx_ctx->ekh_mkey, HDCP_AKE_MKEY_BYTE_LEN); #endif return 0; } static int cap_lc_init(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret; if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL) || (rx_ctx == NULL)) return ERR_WRONG_BUFFER; /* Generate rn */ ret = lc_generate_rn(tx_ctx->rn, HDCP_RTX_BYTE_LEN); if (ret) { hdcp_err("failed to generate rtx\n"); return ERR_GENERATE_RN; } /* Make Message */ m[0] = LC_INIT; memcpy(&m[1], tx_ctx->rn, HDCP_RTX_BYTE_LEN); *m_len = 1 + HDCP_RTX_BYTE_LEN; if ((rx_ctx->version != HDCP_VERSION_2_0) && tx_ctx->lc_precomp && rx_ctx->lc_precomp) { /* compute HMAC, * return the least significant 128-bits, * the most significant 128-bits wrapped */ ret = lc_make_hmac(tx_ctx, rx_ctx, 0); // last param 0 have to be checked, PKY if (ret) return ret; } #ifdef HDCP_LC_DEBUG hdcp_debug("LC_Init(%u)\n", *m_len); hdcp_hexdump(m, *m_len); #endif return 0; } static int cap_rtt_challenge(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL)) return ERR_WRONG_BUFFER; /* Make Message */ m[0] = RTT_CHALLENGE; memcpy(&m[1], tx_ctx->lsb16_hmac, HDCP_HMAC_SHA256_LEN / 2); *m_len = 1 + (HDCP_HMAC_SHA256_LEN / 2); #ifdef HDCP_LC_DEBUG hdcp_debug("RTT_Challenge(%lu)\n", *m_len); hdcp_hexdump(m, *m_lne); #endif return 0; } static int decap_lc_send_l_prime(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { uint8_t *rx_hmac; size_t len; int ret; /* find length depending precomputation */ if ((rx_ctx->version == HDCP_VERSION_2_0) || !tx_ctx->lc_precomp || !rx_ctx->lc_precomp) len = HDCP_HMAC_SHA256_LEN; else len = HDCP_HMAC_SHA256_LEN/2; ret = check_received_msg(m, *m_len, 1 + len, LC_SEND_L_PRIME); if (ret) return ret; /* No_precomputation: compare hmac precomputation: compare the most significant 128bits of L & L' */ rx_hmac = &m[1]; ret = lc_compare_hmac(rx_hmac, len); if (ret) return ret; #ifdef HDCP_LC_DEBUG hdcp_debug("LC_Send_L_prime\n"); hdcp_debug("rx_hmac:\n"); hdcp_hexdump(rx_hmac, len); #endif return 0; } static int decap_rtt_ready(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret; ret = check_received_msg(m, *m_len, 1, RTT_READY); if (ret) return ret; #ifdef HDCP_LC_DEBUG hdcp_debug("RTT_Ready\n"); #endif return 0; } static int cap_ske_send_eks(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret; uint8_t enc_skey[HDCP_AKE_MKEY_BYTE_LEN]; if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL) || (rx_ctx == NULL)) return ERR_WRONG_BUFFER; /* Generate riv */ if (!tx_ctx->share_skey) { ret = ske_generate_riv(tx_ctx->riv); if (ret) return ERR_GENERATE_RIV; } /* Generate encrypted Session Key */ ret = ske_generate_sessionkey(0, enc_skey, tx_ctx->share_skey); if (ret) return ret; /* Make Message */ m[0] = SKE_SEND_EKS; memcpy(&m[1], enc_skey, HDCP_AKE_MKEY_BYTE_LEN); memcpy(&m[1 + HDCP_AKE_MKEY_BYTE_LEN], tx_ctx->riv, HDCP_RTX_BYTE_LEN); *m_len = 1 + HDCP_AKE_MKEY_BYTE_LEN + HDCP_RTX_BYTE_LEN; #ifdef HDCP_SKE_DEBUG hdcp_debug("SKE_Send_Eks(%lu)\n", *m_len); hdcp_hexdump(m, *m_len); #endif return 0; } #ifdef TEST_HDCP_V2_0 int parse_rcvid_list(uint8_t *msg, struct hdcp_tx_ctx *tx_ctx) { /* get PRE META values */ tx_ctx->rcv_list.devs_exd = (uint8_t)*msg; tx_ctx->rcv_list.cascade_exd = (uint8_t)*(msg + 1); /* get META values */ msg += HDCP_RP_RCV_LIST_PRE_META_LEN; tx_ctx->rcv_list.devs_count = (uint8_t)*msg; tx_ctx->rcv_list.depth = (uint8_t)*(msg + 1); memcpy(tx_ctx->rcv_list.hmac_prime, (uint8_t *)(msg + 2), 32); /* get receiver ID list */ msg += 34; memcpy(tx_ctx->rcv_list.rcv_id, msg, tx_ctx->rcv_list.devs_count * HDCP_RCV_ID_LEN); return 0; } void convert_rcvlist2authmsg(struct hdcp_rcvlist *rcv_list, uint8_t *src_msg, size_t *msg_len) { int i; *msg_len = 0; for (i = 0; i < rcv_list->devs_count; i++) { memcpy(src_msg + *msg_len, rcv_list->rcv_id[i], HDCP_RCV_ID_LEN); *msg_len += HDCP_RCV_ID_LEN; } /* concatinate DEPTH */ memcpy(src_msg + *msg_len, &rcv_list->depth, 1); *msg_len += 1; /* concatinate DEVICE COUNT */ memcpy(src_msg + *msg_len, &rcv_list->devs_count, 1); *msg_len += 1; /* concatinate MAX DEVS EXCEEDED */ memcpy(src_msg + *msg_len, &rcv_list->devs_exd, 1); *msg_len += 1; /* concatinate MAX CASCADE EXCEEDED */ memcpy(src_msg + *msg_len, &rcv_list->cascade_exd, 1); *msg_len += 1; } #else int parse_rcvid_list(uint8_t *msg, struct hdcp_tx_ctx *tx_ctx) { /* get PRE META values */ tx_ctx->rpauth_info.devs_exd = (uint8_t)*msg; tx_ctx->rpauth_info.cascade_exd = (uint8_t)*(msg + 1); /* get META values */ msg += HDCP_RP_RCV_LIST_PRE_META_LEN; tx_ctx->rpauth_info.devs_count = (uint8_t)*msg; tx_ctx->rpauth_info.depth = (uint8_t)*(msg + 1); tx_ctx->rpauth_info.hdcp2_down = (uint8_t)*(msg + 2); tx_ctx->rpauth_info.hdcp1_down = (uint8_t)*(msg + 3); memcpy(tx_ctx->rpauth_info.seq_num_v, (uint8_t *)(msg + 4), 3); memcpy(tx_ctx->rpauth_info.v_prime, (uint8_t *)(msg + 7), 16); /* get receiver ID list */ msg += HDCP_RP_RCV_LIST_META_LEN; if (tx_ctx->rpauth_info.devs_count > HDCP_RCV_DEVS_COUNT_MAX) { hdcp_err("invalid DEVS count (%d)\n", tx_ctx->rpauth_info.devs_count); return -1; } memcpy(tx_ctx->rpauth_info.u_rcvid.arr, msg, tx_ctx->rpauth_info.devs_count * HDCP_RCV_ID_LEN); return 0; } void convert_rcvlist2authmsg(struct hdcp_rpauth_info *rpauth_info, uint8_t *src_msg, size_t *msg_len) { int i; *msg_len = 0; for (i = 0; i < rpauth_info->devs_count; i++) { memcpy(src_msg + *msg_len, rpauth_info->u_rcvid.arr[i], HDCP_RCV_ID_LEN); *msg_len += HDCP_RCV_ID_LEN; } /* concatinate DEPTH */ memcpy(src_msg + *msg_len, &rpauth_info->depth, 1); *msg_len += 1; /* concatinate DEVICE COUNT */ memcpy(src_msg + *msg_len, &rpauth_info->devs_count, 1); *msg_len += 1; /* concatinate MAX DEVS EXCEEDED */ memcpy(src_msg + *msg_len, &rpauth_info->devs_exd, 1); *msg_len += 1; /* concatinate MAX CASCADE EXCEEDED */ memcpy(src_msg + *msg_len, &rpauth_info->cascade_exd, 1); *msg_len += 1; /* concatinate HDCP2 REPEATER DOWNSTREAM */ memcpy(src_msg + *msg_len, &rpauth_info->hdcp2_down, 1); *msg_len += 1; /* concatinate HDCP1 DEVICE DOWNSTREAM */ memcpy(src_msg + *msg_len, &rpauth_info->hdcp1_down, 1); *msg_len += 1; /* concatinate seq_num_v */ memcpy(src_msg + *msg_len, &rpauth_info->seq_num_v, 3); *msg_len += 3; } #endif static int decap_RepeaterAuth_send_ReceiverID_List(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { size_t hmac_prime_len; size_t msg_len; uint8_t source_msg[256]; int ret; if (rx_ctx->version == HDCP_VERSION_2_0) hmac_prime_len = HDCP_HMAC_SHA256_LEN; else hmac_prime_len = HDCP_HMAC_SHA256_LEN/2; ret = check_received_msg(m, *m_len, 0, REPEATERAUTH_SEND_RECEIVERID_LIST); if (ret) return ret; if (parse_rcvid_list(m + 1, tx_ctx)) return -1; convert_rcvlist2authmsg(&tx_ctx->rpauth_info, source_msg, &msg_len); ret = teei_set_rcvlist_info(NULL, NULL, tx_ctx->rpauth_info.v_prime, source_msg, tx_ctx->rpauth_info.v, &(tx_ctx->rpauth_info.valid)); tx_ctx->rpauth_info.valid = 0; if (ret) { tx_ctx->rpauth_info.valid = 1; return ret; } #ifdef HDCP_TX_REPEATER_DEBUG hdcp_debug("decap_RepeaterAuth_send_ReceiverID_List valid (%u)\n", tx_ctx->rpauth_info.valid); hdcp_hexdump(tx_ctx->rpauth_info.v, HDCP_RP_HMAC_V_LEN / 2); #endif return 0; } static int cap_RepeaterAuth_Send_Ack(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL)) return ERR_WRONG_BUFFER; /* Make Message */ m[0] = REPEATERAUTH_SEND_ACK; if(tx_ctx->rpauth_info.valid == 0) memcpy(&m[1], tx_ctx->rpauth_info.v, HDCP_RP_HMAC_V_LEN / 2); else return ERR_SEND_ACK; *m_len = 1 + (HDCP_RP_HMAC_V_LEN / 2); #ifdef HDCP_TX_REPEATER_DEBUG hdcp_debug("make_RepeaterAuth_Send_Ack(%u)\n", *m_len); hdcp_hexdump(m, *m_len); #endif return 0; } static int decap_Receiver_AuthStatus(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret; ret = check_received_msg(m, (int)*m_len, 0, RECEIVER_AUTHSTATUS); if (ret) return ret; tx_ctx->rp_reauth = m[3]; #ifdef HDCP_TX_REPEATER_DEBUG hdcp_debug("get_Receiver_AuthStatus(%u)\n", *m_len); hdcp_debug("receiver reauth req: %u\n", tx_ctx->rp_reauth); #endif return 0; } int cap_RepeaterAuth_Stream_Manage(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int i; uint8_t *dst; uint16_t stmp; uint32_t itmp; if ((m == NULL) || (m_len == NULL) || (tx_ctx == NULL)) return ERR_WRONG_BUFFER; if (tx_ctx->stream_ctrl.str_num > HDCP_TX_REPEATER_MAX_STREAM) return ERR_EXCEED_MAX_STREAM; /* Make Message */ m[0] = REPEATERAUTH_STREAM_MANAGE; itmp = htonl(tx_ctx->seq_num_M); memcpy(&m[1], (uint8_t *)&itmp + 1, 3); stmp = htons(tx_ctx->stream_ctrl.str_num); memcpy(&m[4], &stmp, sizeof(stmp)); for (i = 0; i < tx_ctx->stream_ctrl.str_num; i++) { dst = (uint8_t *)(&m[6] + STREAM_INFO_SIZE * i); itmp = htonl(tx_ctx->stream_ctrl.str_info[i].ctr); memcpy(dst, &itmp, sizeof(itmp)); stmp = htons(tx_ctx->stream_ctrl.str_info[i].pid); memcpy(dst + sizeof(itmp), &stmp, sizeof(stmp)); dst[STREAM_INFO_SIZE - 1] = tx_ctx->stream_ctrl.str_info[i].type; } *m_len = HDCP_PROTO_MSG_ID_LEN + STREAM_ELEM_SIZE + STREAM_INFO_SIZE * i; /* seq_num_M++ */ tx_ctx->seq_num_M++; /* save message to make M */ memcpy(tx_ctx->strmsg, &m[6], *m_len - 6); memcpy(tx_ctx->strmsg + *m_len - 6, &m[1], 3); tx_ctx->strmsg_len = *m_len - 3; #ifdef HDCP_TX_REPEATER_DEBUG hdcp_debug("strmsg(len: %d): \n", tx_ctx->strmsg_len); hdcp_hexdump(tx_ctx->strmsg, tx_ctx->strmsg_len); hdcp_debug("message(len: %d): \n", *m_len); hdcp_hexdump(m, *m_len); hdcp_debug("seq_num_M: %d\n", tx_ctx->seq_num_M); #endif return 0; } int decap_RepeaterAuth_Stream_Ready(uint8_t *m, size_t *m_len, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret = 0; /* Not support yet*/ #if 0 ret = check_received_msg(m, *m_len, 1 + HDCP_HMAC_SHA256_LEN, REPEATERAUTH_STREAM_READY); if (ret) return ret; /* compute M and compare M == M' */ ret = teei_verify_m_prime(&m[1], tx_ctx->strmsg, tx_ctx->strmsg_len); if (ret) return ret; #endif return ret; } int cap_protocol_msg(uint8_t msg_id, uint8_t *msg, size_t *msg_len, uint32_t lk_type, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { /* todo: check upper boundary */ int ret = 0; int (**proto_func)(uint8_t *, size_t *, struct hdcp_tx_ctx *, struct hdcp_rx_ctx *); if (lk_type == HDCP_LINK_TYPE_IIA) proto_func = proto_iia; #if defined(CONFIG_HDCP2_DP_ENABLE) else if(lk_type == HDCP_LINK_TYPE_DP) proto_func = proto_dp; #endif else { hdcp_err("invalid link type(%d)\n", lk_type); return -1; } if (msg_id > 1) { ret = proto_func[msg_id - 2](msg, msg_len, tx_ctx, rx_ctx); return ret; } else return -1; } int decap_protocol_msg(uint8_t msg_id, uint8_t *msg, size_t msg_len, uint32_t lk_type, struct hdcp_tx_ctx *tx_ctx, struct hdcp_rx_ctx *rx_ctx) { int ret = 0; int (**proto_func)(uint8_t *, size_t *, struct hdcp_tx_ctx *, struct hdcp_rx_ctx *); /* todo: check upper boundary */ if (lk_type == HDCP_LINK_TYPE_IIA) proto_func = proto_iia; #if defined(CONFIG_HDCP2_DP_ENABLE) else if(lk_type == HDCP_LINK_TYPE_DP) proto_func = proto_dp; #endif else { hdcp_err("HDCP: invalid link type(%d)\n", lk_type); return -1; } if (msg_id > 1) { ret = proto_func[msg_id - 2](msg, &msg_len, tx_ctx, rx_ctx); return ret; } else return -1; }