summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2014-11-04 12:57:06 +1000
committerDave Airlie <airlied@redhat.com>2014-11-04 12:57:06 +1000
commit87919bc43fe09bbdebbb3601f47334a885a0886a (patch)
treee172eeaee87be1c1b2a7f879ce7ee5ab1c40d912
parentd5f1826803f464f093110184c98e8e1248df7fc6 (diff)
finish off SKE bits
also cleanup constant handing around, fix seq numbers
-rw-r--r--dl3.c142
-rw-r--r--dl3_hdcp.c19
-rw-r--r--dl_pkts.h8
-rw-r--r--hdcp.h2
4 files changed, 127 insertions, 44 deletions
diff --git a/dl3.c b/dl3.c
index 6399442..68328a2 100644
--- a/dl3.c
+++ b/dl3.c
@@ -20,6 +20,8 @@
#include <gcrypt.h>
+#define KD_SIZE 32
+
struct hdcp_session_info {
gcry_sexp_t pub_key;
uint8_t calc_h[32];
@@ -29,6 +31,12 @@ struct hdcp_session_info {
bool l_matches;
bool is_repeater;
bool got_h_prime;
+ EVP_CIPHER_CTX aes_ctx; /* ctx for cipher */
+ uint8_t kd[KD_SIZE];
+ uint8_t edkey_ks[16];
+ uint8_t *rtx;
+ uint8_t *km;
+ uint8_t *ks;
};
static int VID = 0x17e9;
static int PID = 0x4301;
@@ -37,10 +45,15 @@ static int PID = 0x4301;
static unsigned char mykm[16] = { 0xcd, 0xef, 0x65, 0x33, 0x69, 0x23, 0xfa, 0x3e,
0x60, 0xee, 0xdd, 0x5c, 0xce, 0xfb, 0x39, 0x19 };
-const uint8_t Rtx[] = { 0x84, 0xd7, 0xcf, 0x64, 0x2d, 0x68, 0xff, 0xd5 };
+static const uint8_t Rtx[] = { 0x84, 0xd7, 0xcf, 0x64, 0x2d, 0x68, 0xff, 0xd5 };
-const uint8_t lc_Rn[] = { 0xd7, 0xfa, 0xf6, 0x99, 0x14, 0xd2, 0x51, 0xe0 };
+static const uint8_t lc_Rn[] = { 0xd7, 0xfa, 0xf6, 0x99, 0x14, 0xd2, 0x51, 0xe0 };
+static const uint8_t riv[] = { 0xea, 0xc1, 0x6d, 0xd3, 0x07, 0xf0, 0x5c, 0x9b};
+
+/* session key */
+static unsigned char myks[16] = { 0xcf, 0xef, 0x65, 0x33, 0x69, 0x23, 0xfa, 0x3e,
+ 0x61, 0xee, 0xdd, 0x5c, 0xce, 0xfb, 0x39, 0x19};
static int create_gcrypt_pubkey(struct hdcp_session_info *info,
const uint8_t *n,
const uint8_t *e,
@@ -109,50 +122,91 @@ static int create_gcrypt_km(gcry_sexp_t *km,
#define KD_SIZE 32
#define NULL_BYTES \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-static uint8_t *kd(uint8_t *km, uint8_t *rtx)
+
+static void calculate_kd(struct hdcp_session_info *info)
{
- EVP_CIPHER_CTX ctx;
- uint8_t *buf = malloc(KD_SIZE);
+ uint8_t *buf;
unsigned char input[] = {NULL_BYTES, NULL_BYTES};
uint8_t iv[16];
uint8_t tmp[100];
int outl;
int ret;
+
+ buf = info->kd;
memset(buf, 0, KD_SIZE);
- memset(iv, 0, 16);
- memcpy(iv, rtx, 8);
+ memset(iv, 0, 16);
- EVP_CIPHER_CTX_init(&ctx);
+ memcpy(iv, info->rtx, 8);
- ret = EVP_EncryptInit_ex(&ctx, EVP_aes_128_ctr(), NULL, km, iv);
+ ret = EVP_EncryptInit_ex(&info->aes_ctx, EVP_aes_128_ctr(), NULL, info->km, iv);
assert(ret == 1);
- ret = EVP_EncryptUpdate(&ctx, buf, &outl, input, sizeof(input));
+ ret = EVP_EncryptUpdate(&info->aes_ctx, buf, &outl, input, sizeof(input));
assert(ret == 1);
assert(outl == sizeof(input));
- ret = EVP_EncryptFinal_ex(&ctx, tmp, &outl);
+ ret = EVP_EncryptFinal_ex(&info->aes_ctx, tmp, &outl);
assert(ret == 1);
assert(outl == 0);
iv[sizeof(iv)-1] = 0x01; /* iv is now r_tx|0...01 */
- ret = EVP_EncryptInit_ex(&ctx, EVP_aes_128_ctr(), NULL, km, iv);
+ ret = EVP_EncryptInit_ex(&info->aes_ctx, EVP_aes_128_ctr(), NULL, info->km, iv);
assert(ret == 1);
- ret = EVP_EncryptUpdate(&ctx, &buf[16], &outl, input, sizeof(input));
+ ret = EVP_EncryptUpdate(&info->aes_ctx, &buf[16], &outl, input, sizeof(input));
assert(ret == 1);
assert(outl == sizeof(input));
- ret = EVP_EncryptFinal_ex(&ctx, tmp, &outl);
+ ret = EVP_EncryptFinal_ex(&info->aes_ctx, tmp, &outl);
assert(ret == 1);
assert(outl == 0);
- ret = EVP_CIPHER_CTX_cleanup(&ctx);
+ assert(ret == 1);
+}
+
+static void calculate_edkey_ks(struct hdcp_session_info *info)
+{
+ unsigned char input[] = {NULL_BYTES, NULL_BYTES};
+ uint8_t iv[16];
+ uint8_t *buf = info->edkey_ks;
+ int ret;
+ int outl;
+ uint8_t tmp[100];
+ int i;
+
+ memset(iv, 0, 16);
+
+ memcpy(iv, info->rtx, 8);
+
+ iv[sizeof(iv)-1] = 0x02; /* iv is now r_tx|0...02 */
+
+ ret = EVP_EncryptInit_ex(&info->aes_ctx, EVP_aes_128_ctr(), NULL, info->km, iv);
assert(ret == 1);
- return buf;
+ ret = EVP_EncryptUpdate(&info->aes_ctx, buf, &outl, input, sizeof(input));
+ assert(ret == 1);
+ assert(outl == sizeof(input));
+
+ ret = EVP_EncryptFinal_ex(&info->aes_ctx, tmp, &outl);
+ assert(ret == 1);
+ assert(outl == 0);
+
+ /* we have dkey2 in buf now */
+ printf("dkey2:");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", buf[i]);
+ }
+ printf("\n");
+
+ for (i = 0; i < 8; i++) {
+ buf[8 + i] ^= info->rrx[i];
+ }
+
+ for (i = 0; i < 16; i++) {
+ buf[i] ^= info->ks[i];
+ }
}
static int calculate_h(struct hdcp_session_info *info)
@@ -163,12 +217,12 @@ static int calculate_h(struct hdcp_session_info *info)
int i;
uint8_t input[8];
- memcpy(input, Rtx, 8);
+ memcpy(input, info->rtx, 8);
if (info->is_repeater)
input[7] ^= 0x1;
HMAC_CTX_init(&ctx);
- HMAC_Init_ex(&ctx, kd(mykm, Rtx), KD_SIZE, EVP_sha256(), NULL);
+ HMAC_Init_ex(&ctx, info->kd, KD_SIZE, EVP_sha256(), NULL);
HMAC_Update(&ctx, input, 8);
HMAC_Final(&ctx, res, &resLen);
@@ -188,9 +242,9 @@ static int calculate_l(struct hdcp_session_info *info)
unsigned int resLen;
int i;
uint8_t input[8];
- unsigned char *kdbuf;
+ uint8_t kdbuf[KD_SIZE];
- kdbuf = kd(mykm, Rtx);
+ memcpy(kdbuf, info->kd, KD_SIZE);
for (i = 0; i < 8; i++) {
kdbuf[24 + i] ^= info->rrx[i];
@@ -384,6 +438,9 @@ static void decode_rx(struct hdcp_session_info *info,
case HDCP_LC_SEND_L_PRIME:
decode_l_prime(info, buf + 22, len - 22);
break;
+ case HDCP_REPEATER_AUTH_SEND_RECEIVED_ID_LIST:
+ printf("send received id list\n");
+ break;
}
}
@@ -435,39 +492,45 @@ static int send_buffer(libusb_device_handle *handle, int endpoint_out, int endpo
memset(&info, 0, sizeof(info));
+ EVP_CIPHER_CTX_init(&info.aes_ctx);
+
+ info.rtx = Rtx;
+ info.km = mykm;
+ info.ks = myks;
+
dl3_empty_packet(buf, &len);
r = write_to_usb(handle, endpoint_out, buf, len, &size);
if (r != 0)
- return r;
+ goto out;
dl3_msg2_hdr25(buf, &len);
r = write_to_usb(handle, endpoint_out, buf, len, &size);
if (r != 0)
- return r;
+ goto out;
memset(buf, 0, 1024);
dl3_msg2_hdr04(buf, &len);
len2 = len;
- dl3_packet_hdcp_ake_init(&buf[len], &len, Rtx);
+ dl3_packet_hdcp_ake_init(&buf[len], &len, info.rtx);
len2 += len;
len2 = ROUND_TO_4(len2);
r = write_to_usb(handle, endpoint_out, buf, len2, &size);
if (r != 0)
- return r;
+ goto out;
r = block_read_usb(handle, endpoint_in, buf, &size);
if (r < 0)
- return r;
+ goto out;
decode_rx(&info, buf, size);
r = block_read_usb(handle, endpoint_in, buf, &size);
if (r < 0)
- return r;
+ goto out;
decode_rx(&info, buf, size);
- r = create_gcrypt_km(&km, mykm, 16);
+ r = create_gcrypt_km(&km, info.km, 16);
if (r != 0)
fprintf(stderr, "failed to create km\n");
@@ -489,12 +552,13 @@ static int send_buffer(libusb_device_handle *handle, int endpoint_out, int endpo
dl3_packet_hdcp_ake_no_stored_km(buf, &len, obuf);
/* calculate H */
+ calculate_kd(&info);
calculate_h(&info);
len = ROUND_TO_4(len);
r = write_to_usb(handle, endpoint_out, buf, len, &size);
if (r != 0)
- return r;
+ goto out;
do {
r = block_read_usb(handle, endpoint_in, buf, &size);
@@ -511,7 +575,7 @@ static int send_buffer(libusb_device_handle *handle, int endpoint_out, int endpo
dl3_packet_hdcp_lc_init(buf, &len, lc_Rn);
r = write_to_usb(handle, endpoint_out, buf, len, &size);
if (r != 0)
- return r;
+ goto out;
calculate_l(&info);
do {
@@ -524,7 +588,25 @@ static int send_buffer(libusb_device_handle *handle, int endpoint_out, int endpo
if (!info.l_matches)
return -1;
- return 0;
+
+ calculate_edkey_ks(&info);
+ dl3_packet_hdcp_ske_send_eks(buf, &len, info.edkey_ks, riv);
+ r = write_to_usb(handle, endpoint_out, buf, len, &size);
+ if (r != 0)
+ goto out;
+
+ do {
+ r = block_read_usb(handle, endpoint_in, buf, &size);
+ if (r < 0)
+ break;
+ decode_rx(&info, buf, size);
+ /* find L' */
+ } while (1);
+ r = 0;
+ out:
+ EVP_CIPHER_CTX_cleanup(&info.aes_ctx);
+
+ return r;
}
int test_device(uint16_t vid, uint16_t pid)
diff --git a/dl3_hdcp.c b/dl3_hdcp.c
index c2a8bbf..d2aeea5 100644
--- a/dl3_hdcp.c
+++ b/dl3_hdcp.c
@@ -3,6 +3,7 @@
#include "hdcp.h"
#include "dl_pkts.h"
+static uint16_t out_hdcp_counter;
/* all outgoing packets in bytes - 4-8 - contains one of these values,
4 seems to be used the most, for HDCP packets and data packets.
4 seems to have a subpacket type */
@@ -113,7 +114,7 @@ int pkt4_mid_len(int hdcp_msg_len, int *mid_len)
return total;
}
-void dl3_packet_hdcp_ake_init(uint8_t *buf, int *len_p, uint8_t *Rtx)
+void dl3_packet_hdcp_ake_init(uint8_t *buf, int *len_p, const uint8_t *Rtx)
{
int ake_init_len = 8 + 1;
int total_len = 0;
@@ -127,7 +128,7 @@ void dl3_packet_hdcp_ake_init(uint8_t *buf, int *len_p, uint8_t *Rtx)
fill_hdcp_header1(buf, total_len, MSG_TYPE_4);
fill_hdcp_header2(buf, MSG4_PKT4);
- dl3_msg4_hdr4(buf, mid_len, 0x10, 0);
+ dl3_msg4_hdr4(buf, mid_len, 0x10, out_hdcp_counter++);
buf[38] = 0x30;
buf[40] = HDCP_AKE_INIT;
@@ -141,7 +142,7 @@ void dl3_packet_hdcp_ake_init(uint8_t *buf, int *len_p, uint8_t *Rtx)
}
/* send an empty km for now */
-void dl3_packet_hdcp_ake_no_stored_km(uint8_t *buf, int *len_p, uint8_t *ekpubkm)
+void dl3_packet_hdcp_ake_no_stored_km(uint8_t *buf, int *len_p, const uint8_t *ekpubkm)
{
int nsk_len = 128 + 1;
int total_len, mid_len, i;
@@ -152,7 +153,7 @@ void dl3_packet_hdcp_ake_no_stored_km(uint8_t *buf, int *len_p, uint8_t *ekpubkm
fill_hdcp_header1(buf, total_len, MSG_TYPE_4);
fill_hdcp_header2(buf, MSG4_PKT4);
- dl3_msg4_hdr4(buf, mid_len, 0x10, 0x1);
+ dl3_msg4_hdr4(buf, mid_len, 0x10, out_hdcp_counter++);
buf[38] = 0x30;
buf[40] = HDCP_AKE_NO_STORED_KM;
@@ -163,7 +164,7 @@ void dl3_packet_hdcp_ake_no_stored_km(uint8_t *buf, int *len_p, uint8_t *ekpubkm
*len_p = total_len + 4;
}
-void dl3_packet_hdcp_lc_init(uint8_t *buf, int *len_p, uint8_t *Rn)
+void dl3_packet_hdcp_lc_init(uint8_t *buf, int *len_p, const uint8_t *Rn)
{
int lc_init_len = 8 + 1;
int total_len = 0;
@@ -177,7 +178,7 @@ void dl3_packet_hdcp_lc_init(uint8_t *buf, int *len_p, uint8_t *Rn)
fill_hdcp_header1(buf, total_len, MSG_TYPE_4);
fill_hdcp_header2(buf, MSG4_PKT4);
- dl3_msg4_hdr4(buf, mid_len, 0x10, 0);
+ dl3_msg4_hdr4(buf, mid_len, 0x10, out_hdcp_counter++);
buf[38] = 0x30;
buf[40] = HDCP_LC_INIT;
@@ -190,21 +191,21 @@ void dl3_packet_hdcp_lc_init(uint8_t *buf, int *len_p, uint8_t *Rn)
*len_p = total_len + 4;
}
-void dl3_packet_hdcp_ske_send_eks(uint8_t *buf, int *len_p, uint8_t *edkey_ks, uint8_t *riv)
+void dl3_packet_hdcp_ske_send_eks(uint8_t *buf, int *len_p, const uint8_t *edkey_ks, const uint8_t *riv)
{
int ske_send_eks_len = 24 + 1;
int total_len = 0;
int i;
int mid_len;
- /* 9 bytes for AKE */
+ /* 24 bytes for ske send eks */
total_len = pkt4_mid_len(ske_send_eks_len, &mid_len);
memset(buf, 0, ROUND_TO_4(total_len + 4));
fill_hdcp_header1(buf, total_len, MSG_TYPE_4);
fill_hdcp_header2(buf, MSG4_PKT4);
- dl3_msg4_hdr4(buf, mid_len, 0x10, 0);
+ dl3_msg4_hdr4(buf, mid_len, 0x10, out_hdcp_counter++);
buf[38] = 0x30;
buf[40] = HDCP_SKE_SEND_EKS;
diff --git a/dl_pkts.h b/dl_pkts.h
index d3142e8..f78d2d6 100644
--- a/dl_pkts.h
+++ b/dl_pkts.h
@@ -5,9 +5,9 @@
void dl3_empty_packet(uint8_t *buf, int *len);
void dl3_msg2_hdr25(uint8_t *buf, int *len_p);
void dl3_msg2_hdr04(uint8_t *buf, int *len_p);
-void dl3_packet_hdcp_ake_init(uint8_t *buf, int *len_p, uint8_t *Rtx);
-void dl3_packet_hdcp_ake_no_stored_km(uint8_t *buf, int *len_p, uint8_t *ekpubkm);
-void dl3_packet_hdcp_lc_init(uint8_t *buf, int *len_p, uint8_t *Rn);
-void dl3_packet_hdcp_ske_send_eks(uint8_t *buf, int *len_p, uint8_t *edkey_ks, uint8_t *riv);
+void dl3_packet_hdcp_ake_init(uint8_t *buf, int *len_p, const uint8_t *Rtx);
+void dl3_packet_hdcp_ake_no_stored_km(uint8_t *buf, int *len_p, const uint8_t *ekpubkm);
+void dl3_packet_hdcp_lc_init(uint8_t *buf, int *len_p, const uint8_t *Rn);
+void dl3_packet_hdcp_ske_send_eks(uint8_t *buf, int *len_p, const uint8_t *edkey_ks, const uint8_t *riv);
#define ROUND_TO_4(x) ((((x) + 3) / 4) * 4)
#endif
diff --git a/hdcp.h b/hdcp.h
index 5b362be..21302ec 100644
--- a/hdcp.h
+++ b/hdcp.h
@@ -11,5 +11,5 @@
#define HDCP_LC_INIT 9
#define HDCP_LC_SEND_L_PRIME 10
#define HDCP_SKE_SEND_EKS 11
-
+#define HDCP_REPEATER_AUTH_SEND_RECEIVED_ID_LIST 12
#endif