summaryrefslogtreecommitdiff
path: root/dl3_hdcp.c
blob: 9a06712632aabb0bc24fbd866b40a7dbf5316f76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#include <stdint.h>
#include <string.h>
#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 */
#define MSG_TYPE_1 0x1
#define MSG_TYPE_2 0x2
#define MSG_TYPE_4 0x4

/* seems to be an initial 8 byte header on USB outgoing packets */
static void fill_hdcp_header1(uint8_t *buf, uint16_t length, uint32_t msg_type)
{
	buf[0] = 0;
	buf[1] = 0;

	buf[2] = (length & 0xff);
	buf[3] = (length >> 8) & 0xff;

	/* msg type (??) */
	buf[4] = msg_type & 0xff;
	buf[5] = 0;
	buf[6] = 0;
	buf[7] = 0;
}

/* header 2 values seen in traces */
/* MSG1 hdr2 values */
#define MSG1_0 0x0    /* null header - no more data */

/* MSG2 hdr2 values */
#define MSG2_04 0x04  /* appears first at init time - has 16 bytes following. */
#define MSG2_06 0x06  /* appears first at init time - has 16 bytes following. */
#define MSG2_25 0x25  /* appears first at init time - has 16 bytes following. */
/* hdr25 appears to have a sequence number following it. */
/* 4 appears in MSG2 and MSG4 headers */
#define MSG2_45 0x45 /* mostly seems to be input - sent once */

/* 4 in the header seems to have a subtype */
#define MSG4_PKT4  0x04 /* use in HDCP transactions, AKE etc */
#define MSG4_PKT6  0x06 /* use in HDCP data transactions with enc data */

#define MSG4_PKT25 0x25 /* used for replies */
#define MSG4_PKT45 0x45 /* used for replies */

/* MSG4 HDR2 4/25 - has a secondary length/type field at 0x16
   0x10 - non HDCP
   0x84 - HDCP msg
*/
/* seems to be a secondary 8 byte header on outgoing packets */
/* appears to get filled in for type 6 dwords */
static void fill_hdcp_header2(uint8_t *buf, uint32_t dword)
{
	int i;

	buf[8] = dword & 0xff;
	for (i = 9; i < 16; i++)
		buf[i] = 0x0;
}

void dl3_empty_packet(uint8_t *buf, int *len)
{
	memset(buf, 0, 16);
	fill_hdcp_header1(buf, 12, MSG_TYPE_1);
	fill_hdcp_header2(buf, MSG1_0);
	*len = 16;
}

void dl3_msg2_hdr(uint8_t *buf, int *len_p, int hdr_num,
		  uint16_t val1, uint16_t val2)
{
	int len = 0x1c;
	memset(buf, 0, len + 4);
	fill_hdcp_header1(buf, len, MSG_TYPE_2);
	fill_hdcp_header2(buf, hdr_num);

	buf[16] = val1 & 0xff;
	buf[18] = val2 & 0xff;

	*len_p = len + 4;
}

void dl3_msg4_hdr4(uint8_t *buf, uint16_t length, uint16_t type, uint16_t seq)
{
	buf[16] = (length & 0xff);
	buf[17] = (length >> 8) & 0xff;
	buf[18] = (type & 0xff);
	buf[19] = (type >> 8) & 0xff;
	buf[20] = (seq & 0xff);
	buf[21] = (seq >> 8) & 0xff;
}

int pkt4_mid_len(int hdcp_msg_len, int *mid_len)
{
	int total;
	total = hdcp_msg_len;
	total += 22;
	*mid_len = total;
	total += 14;
	return total;
}

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;
	int i;
	int mid_len;

	/* 9 bytes for AKE */
	total_len = pkt4_mid_len(ake_init_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, out_hdcp_counter++);

	buf[38] = 0x30;
	buf[40] = HDCP_AKE_INIT;

	/* write Rtx */
	for (i = 0; i < 8; i++) {
		buf[41 + i] = Rtx[i];
	}

	*len_p = total_len + 4;
}

/* send an empty km for now */
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;

	total_len = pkt4_mid_len(nsk_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, out_hdcp_counter++);

	buf[38] = 0x30;
	buf[40] = HDCP_AKE_NO_STORED_KM;

	for (i = 0; i < 128; i++) {
	  buf[41 + i] = ekpubkm[i];
	}
	*len_p = total_len + 4;
}

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;
	int i;
	int mid_len;

	/* 9 bytes for AKE */
	total_len = pkt4_mid_len(lc_init_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, out_hdcp_counter++);

	buf[38] = 0x30;
	buf[40] = HDCP_LC_INIT;

	/* write Rtx */
	for (i = 0; i < 8; i++) {
		buf[41 + i] = Rn[i];
	}

	*len_p = total_len + 4;
}

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;

	/* 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, out_hdcp_counter++);

	buf[38] = 0x30;
	buf[40] = HDCP_SKE_SEND_EKS;

	/* write Rtx */
	for (i = 0; i < 16; i++) {
		buf[41 + i] = edkey_ks[i];
	}
	for (i = 0; i < 8; i++) {
		buf[41 + 16 + i] = riv[i];
	}

	*len_p = total_len + 4;
}

void dl3_packet_send_enc_data(uint8_t *buf, int *len_p, const uint8_t *enc_data)
{
	int total_len = 0;

	total_len = 48 + 12;

	memset(buf, 0, ROUND_TO_4(total_len + 4));
	fill_hdcp_header1(buf, total_len, MSG_TYPE_4);
	fill_hdcp_header2(buf, MSG4_PKT6);

	buf[10] = 0xa;

	memcpy(&buf[16], enc_data, 48);
	*len_p = total_len + 4;
}