diff options
author | Dave Airlie <airlied@redhat.com> | 2014-11-04 12:57:06 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-11-04 12:57:06 +1000 |
commit | 87919bc43fe09bbdebbb3601f47334a885a0886a (patch) | |
tree | e172eeaee87be1c1b2a7f879ce7ee5ab1c40d912 | |
parent | d5f1826803f464f093110184c98e8e1248df7fc6 (diff) |
finish off SKE bits
also cleanup constant handing around,
fix seq numbers
-rw-r--r-- | dl3.c | 142 | ||||
-rw-r--r-- | dl3_hdcp.c | 19 | ||||
-rw-r--r-- | dl_pkts.h | 8 | ||||
-rw-r--r-- | hdcp.h | 2 |
4 files changed, 127 insertions, 44 deletions
@@ -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) @@ -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; @@ -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 @@ -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 |