diff options
Diffstat (limited to 'dl3.c')
-rw-r--r-- | dl3.c | 95 |
1 files changed, 93 insertions, 2 deletions
@@ -23,8 +23,12 @@ struct hdcp_session_info { gcry_sexp_t pub_key; uint8_t calc_h[32]; + uint8_t calc_l[32]; + uint8_t rrx[8]; bool h_matches; + bool l_matches; bool is_repeater; + bool got_h_prime; }; static int VID = 0x17e9; static int PID = 0x4301; @@ -35,6 +39,8 @@ static unsigned char mykm[16] = { 0xcd, 0xef, 0x65, 0x33, 0x69, 0x23, 0xfa, 0x3e 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 int create_gcrypt_pubkey(struct hdcp_session_info *info, const uint8_t *n, const uint8_t *e, @@ -174,6 +180,35 @@ static int calculate_h(struct hdcp_session_info *info) memcpy(info->calc_h, res, resLen); } +static int calculate_l(struct hdcp_session_info *info) +{ + HMAC_CTX ctx; + unsigned char res[200]; + unsigned int resLen; + int i; + uint8_t input[8]; + unsigned char *kdbuf; + + kdbuf = kd(mykm, Rtx); + + for (i = 0; i < 8; i++) { + kdbuf[24 + i] ^= info->rrx[i]; + } + memcpy(input, lc_Rn, 8); + + HMAC_CTX_init(&ctx); + HMAC_Init_ex(&ctx, kdbuf, KD_SIZE, EVP_sha256(), NULL); + HMAC_Update(&ctx, input, 8); + HMAC_Final(&ctx, res, &resLen); + + HMAC_CTX_cleanup(&ctx); + + if (resLen != 32) + return -1; + + memcpy(info->calc_l, res, resLen); +} + static void decode_cert(struct hdcp_session_info *info, const uint8_t *buf, int len) { const uint8_t *start = buf + 2; @@ -256,6 +291,13 @@ static void decode_cert(struct hdcp_session_info *info, const uint8_t *buf, int printf("ret is %d\n", ret); } +static void decode_rrx(struct hdcp_session_info *info, + const uint8_t *buf, int len) +{ + const uint8_t *start = buf + 1; + memcpy(info->rrx, start, 8); +} + static void decode_h_prime(struct hdcp_session_info *info, const uint8_t *buf, int len) { @@ -279,6 +321,34 @@ static void decode_h_prime(struct hdcp_session_info *info, } +static void decode_l_prime(struct hdcp_session_info *info, + const uint8_t *buf, int len) +{ + const uint8_t *start = buf + 1; + int i; + + if (!memcmp(info->calc_l, start, 32)) { + info->l_matches = true; + printf("L values matched\n"); + return; + } else { + info->l_matches = false; + printf("L values failed to match\n"); + } + printf("l: "); + for (i = 0; i < 32; i++) { + printf("%02x", info->calc_l[i]); + } + printf("\n"); + printf("l_prime: "); + for (i = 0; i < 32; i++) { + printf("%02x", start[i]); + } + + printf("\n"); + +} + static void decode_rx(struct hdcp_session_info *info, const uint8_t *buf, int len) { @@ -301,7 +371,7 @@ static void decode_rx(struct hdcp_session_info *info, decode_cert(info, buf + 22, len - 22); break; case HDCP_AKE_SEND_RRX: - printf("send rrx\n"); + decode_rrx(info, buf + 22, len - 22); break; case HDCP_AKE_SEND_H_PRIME: decode_h_prime(info, buf + 22, len - 22); @@ -309,6 +379,9 @@ static void decode_rx(struct hdcp_session_info *info, case HDCP_AKE_SEND_PAIRING_INFO: printf("send pairing info\n"); break; + case HDCP_LC_SEND_L_PRIME: + decode_l_prime(info, buf + 22, len - 22); + break; } } @@ -424,10 +497,28 @@ static int send_buffer(libusb_device_handle *handle, int endpoint_out, int endpo do { r = block_read_usb(handle, endpoint_in, buf, &size); if (r < 0) - return r; + break; decode_rx(&info, buf, size); /* find H' */ } while (1); + + if (!info.h_matches) + return -1; + + /* send LC prime */ + dl3_packet_hdcp_lc_init(buf, &len, lc_Rn); + r = write_to_usb(handle, endpoint_out, buf, len, &size); + if (r != 0) + return r; + + calculate_l(&info); + do { + r = block_read_usb(handle, endpoint_in, buf, &size); + if (r < 0) + break; + decode_rx(&info, buf, size); + /* find L' */ + } while (1); return 0; } |