1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "hdf_log.h"
10 #include "hdmi_core.h"
11
12 #define HDF_LOG_TAG hdmi_hdcp_c
13
HdmiHdcpRead(struct HdmiHdcp * hdcp,enum HdmiHdcpPortOffset offset,uint8_t * buffer,uint32_t len)14 static int32_t HdmiHdcpRead(struct HdmiHdcp *hdcp, enum HdmiHdcpPortOffset offset, uint8_t *buffer, uint32_t len)
15 {
16 struct HdmiDdcCfg cfg = {0};
17 struct HdmiCntlr *cntlr = NULL;
18
19 if (hdcp == NULL || hdcp->priv == NULL) {
20 return HDF_ERR_INVALID_PARAM;
21 }
22
23 cntlr = (struct HdmiCntlr *)hdcp->priv;
24 cfg.type = HDMI_DDC_DEV_HDCP;
25 cfg.readFlag = true;
26 cfg.devAddr = HDMI_DDC_HDCP_DEV_ADDRESS;
27 cfg.data = buffer;
28 cfg.dataLen = len;
29 cfg.offset = offset;
30 cfg.mode = HDMI_DDC_MODE_READ_MUTIL_NO_ACK;
31 return HdmiDdcTransfer(&(cntlr->ddc), &cfg);
32 }
33
HdmiHdcpWrite(struct HdmiHdcp * hdcp,enum HdmiHdcpPortOffset offset,uint8_t * buffer,uint32_t len)34 static int32_t HdmiHdcpWrite(struct HdmiHdcp *hdcp, enum HdmiHdcpPortOffset offset, uint8_t *buffer, uint32_t len)
35 {
36 struct HdmiDdcCfg cfg = {0};
37 struct HdmiCntlr *cntlr = NULL;
38
39 if (hdcp == NULL || hdcp->priv == NULL) {
40 return HDF_ERR_INVALID_PARAM;
41 }
42
43 cntlr = (struct HdmiCntlr *)hdcp->priv;
44 cfg.type = HDMI_DDC_DEV_HDCP;
45 cfg.readFlag = false;
46 cfg.devAddr = HDMI_DDC_HDCP_DEV_ADDRESS;
47 cfg.data = buffer;
48 cfg.dataLen = len;
49 cfg.offset = offset;
50 cfg.mode = HDMI_DDC_MODE_WRITE_MUTIL_ACK;
51 return HdmiDdcTransfer(&(cntlr->ddc), &cfg);
52 }
53
HdmiHdcpCheckKvs(uint8_t * ksv,uint32_t len)54 static bool HdmiHdcpCheckKvs(uint8_t *ksv, uint32_t len)
55 {
56 uint32_t i, j;
57 uint32_t cnt = 0;
58
59 for (i = 0; i < len; i++) {
60 for (j = 0; j < HDMI_ONE_BYTE_SHIFT; j++) {
61 if (((ksv[i] >> j) & 0x01) > 0) {
62 cnt++;
63 }
64 }
65 }
66 /* KSV contains 20 ones and 20 zeros. */
67 if (cnt != HDMI_HDCP_AKSV_ONE_NUM) {
68 HDF_LOGE("HdmiHdcpCheckKvs: cnt = %d.", cnt);
69 return false;
70 }
71 return true;
72 }
73
HdmiHdcpWriteMsgToReg(struct HdmiHdcp * hdcp,enum HdmiHdcpRegOptType type,uint8_t * data,uint32_t len)74 static int32_t HdmiHdcpWriteMsgToReg(struct HdmiHdcp *hdcp, enum HdmiHdcpRegOptType type, uint8_t *data, uint32_t len)
75 {
76 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)hdcp->priv;
77
78 if (cntlr->ops == NULL || cntlr->ops->hdcpOptReg == NULL) {
79 HDF_LOGD("not support hdcp write reg.");
80 return HDF_ERR_INVALID_PARAM;
81 }
82 return cntlr->ops->hdcpOptReg(cntlr, type, data, len);
83 }
84
HdmiHdcpReadMsgBksv(struct HdmiHdcp * hdcp)85 static int32_t HdmiHdcpReadMsgBksv(struct HdmiHdcp *hdcp)
86 {
87 int32_t ret;
88
89 ret = HdmiHdcpRead(hdcp, HDMI_HDCP_BKSV, hdcp->bksv, sizeof(hdcp->bksv));
90 if (ret != HDF_SUCCESS) {
91 return ret;
92 }
93 if (HdmiHdcpCheckKvs(hdcp->bksv, sizeof(hdcp->bksv)) == false) {
94 HDF_LOGE("auth part I: bksv check fail.");
95 return HDF_ERR_INVALID_PARAM;
96 }
97 return HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_WRITE_BKSV, hdcp->bksv, sizeof(hdcp->bksv));
98 }
99
HdmiHdcpReadMsgRi(struct HdmiHdcp * hdcp)100 static int32_t HdmiHdcpReadMsgRi(struct HdmiHdcp *hdcp)
101 {
102 int32_t ret;
103 ret = HdmiHdcpRead(hdcp, HDMI_HDCP_RI, hdcp->ri, sizeof(hdcp->ri));
104 if (ret != HDF_SUCCESS) {
105 return ret;
106 }
107 return HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_WRITE_RI, hdcp->ri, sizeof(hdcp->ri));
108 }
109
HdmiHdcpWriteMsgAksv(struct HdmiHdcp * hdcp)110 static int32_t HdmiHdcpWriteMsgAksv(struct HdmiHdcp *hdcp)
111 {
112 if (HdmiHdcpCheckKvs(hdcp->aksv, sizeof(hdcp->aksv)) == false) {
113 HDF_LOGE("auth part I: aksv check fail.");
114 return HDF_ERR_INVALID_PARAM;
115 }
116 return HdmiHdcpWrite(hdcp, HDMI_HDCP_AN, hdcp->aksv, sizeof(hdcp->aksv));
117 }
118
HdmiHdcpWriteMsgAn(struct HdmiHdcp * hdcp)119 static int32_t HdmiHdcpWriteMsgAn(struct HdmiHdcp *hdcp)
120 {
121 return HdmiHdcpWrite(hdcp, HDMI_HDCP_AN, hdcp->an, sizeof(hdcp->an));
122 }
123
HdmiHdcpReadMsgHv(struct HdmiHdcp * hdcp)124 static int32_t HdmiHdcpReadMsgHv(struct HdmiHdcp *hdcp)
125 {
126 uint8_t offset, i;
127 uint8_t vhNum = HDMI_HDCP_MSG_ALL_VH_LEN / HDMI_HDCP_MSG_PER_VH_LEN;
128 int32_t ret;
129
130 if (hdcp == NULL) {
131 return HDF_ERR_INVALID_PARAM;
132 }
133
134 for (i = 0; i < vhNum; i++) {
135 offset = HDMI_HDCP_V_H0 + i * HDMI_HDCP_MSG_PER_VH_LEN;
136 ret = HdmiHdcpRead(hdcp, offset, &(hdcp->vh[i]), HDMI_HDCP_MSG_PER_VH_LEN);
137 if (ret != HDF_SUCCESS) {
138 return ret;
139 }
140 }
141 return HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_WRITE_V_H_ALL, hdcp->vh, sizeof(hdcp->vh));
142 }
143
HdmiHdcpReadMsgBcaps(struct HdmiHdcp * hdcp)144 static int32_t HdmiHdcpReadMsgBcaps(struct HdmiHdcp *hdcp)
145 {
146 int32_t ret;
147 ret = HdmiHdcpRead(hdcp, HDMI_HDCP_BCAPS, &(hdcp->bcaps), sizeof(hdcp->bcaps));
148 if (ret != HDF_SUCCESS) {
149 return ret;
150 }
151 return HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_WRITE_BCAPS, &(hdcp->bcaps), sizeof(hdcp->bcaps));
152 }
153
HdmiHdcpAuthenticationGenerateAksvAn(struct HdmiHdcp * hdcp)154 static int32_t HdmiHdcpAuthenticationGenerateAksvAn(struct HdmiHdcp *hdcp)
155 {
156 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)hdcp->priv;
157
158 if (cntlr->ops == NULL || cntlr->ops->hdcpGenerateAksvAndAn == NULL) {
159 return HDF_ERR_NOT_SUPPORT;
160 }
161 return cntlr->ops->hdcpGenerateAksvAndAn(cntlr);
162 }
163
HdmiHdcpRegPrepare(struct HdmiHdcp * hdcp)164 static void HdmiHdcpRegPrepare(struct HdmiHdcp *hdcp)
165 {
166 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)hdcp->priv;
167
168 if (cntlr->ops == NULL || cntlr->ops->hdcpRegInit == NULL) {
169 return;
170 }
171 cntlr->ops->hdcpRegInit(cntlr);
172 }
173
HdmiHdcpAuthenticationPrepare(struct HdmiHdcp * hdcp)174 static int32_t HdmiHdcpAuthenticationPrepare(struct HdmiHdcp *hdcp)
175 {
176 int32_t ret;
177
178 HdmiHdcpRegPrepare(hdcp);
179 if (hdcp->aksvValid == false) {
180 ret = HdmiHdcpAuthenticationGenerateAksvAn(hdcp);
181 if (ret != HDF_SUCCESS) {
182 hdcp->state = HDMI_HDCP_AUTH_AKSV_INVALID;
183 return ret;
184 }
185 }
186 hdcp->aksvValid = true;
187 return HDF_SUCCESS;
188 }
189
HdmiHdcpAuthenticationFirstPart(struct HdmiHdcp * hdcp)190 static int32_t HdmiHdcpAuthenticationFirstPart(struct HdmiHdcp *hdcp)
191 {
192 int32_t ret;
193
194 hdcp->state = HDMI_HDCP_AUTH_DOING;
195 /*
196 * Authentication is initiated by the HDCP Transmitter by sendind an initiation massage containing its KSV(aksv)
197 * and a 64-bit pseudo-random value(An) generated by the HDCP Cipher function hdcpRngCipher to the HDCP Reciever.
198 */
199 ret = HdmiHdcpWriteMsgAksv(hdcp);
200 if (ret != HDF_SUCCESS) {
201 return ret;
202 }
203 ret = HdmiHdcpWriteMsgAn(hdcp);
204 if (ret != HDF_SUCCESS) {
205 return ret;
206 }
207
208 /*
209 * The HDCP Reciever responds by sending a response message containing the receiver's KSV(bksv) and
210 * the REPEATER bit, which indicates if the reciever is an HDCP Repeater.
211 */
212 ret = HdmiHdcpReadMsgBksv(hdcp);
213 if (ret != HDF_SUCCESS) {
214 return ret;
215 }
216 ret = HdmiHdcpReadMsgBcaps(hdcp);
217 if (ret != HDF_SUCCESS) {
218 return ret;
219 }
220
221 /*
222 * The HDCP Transmitter must not read the R0' value sooner than 100ms after writing Aksv.
223 */
224 OsalMSleep(120);
225 /* Read R0' */
226 ret = HdmiHdcpReadMsgRi(hdcp);
227 if (ret != HDF_SUCCESS) {
228 return ret;
229 }
230
231 /* Verify R0/R0' matched or not */
232 ret = HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_CHECK_R, NULL, 0);
233 if (ret != HDF_SUCCESS) {
234 HDF_LOGE("hdcp auth, check V fail.");
235 return ret;
236 }
237 return HDF_SUCCESS;
238 }
239
HdmiHdcpAuthenticationCheckBstatus(struct HdmiHdcp * hdcp)240 static int32_t HdmiHdcpAuthenticationCheckBstatus(struct HdmiHdcp *hdcp)
241 {
242 int32_t ret;
243 uint16_t bstatus;
244
245 ret = HdmiHdcpRead(hdcp, HDMI_HDCP_BSTATUS, hdcp->bstatus, sizeof(hdcp->bstatus));
246 if (ret != HDF_SUCCESS) {
247 return ret;
248 }
249
250 /* phase bstatus. */
251 bstatus = (hdcp->bstatus[1] << 8) | hdcp->bstatus[0];
252 hdcp->deviceCount = bstatus & HDMI_HDCP_BSTATUS_DEVICE_COUNT_MARK;
253 if (hdcp->deviceCount == 0) {
254 HDF_LOGE("hdcp auth, check bstatus, no device attached to the repeater.");
255 return HDF_DEV_ERR_NO_DEVICE;
256 }
257 if ((bstatus & HDMI_HDCP_BSTATUS_MAX_DEVS_EXCEEDED_MARK) > 0) {
258 HDF_LOGE("hdcp auth, check bstatus, exceeds max allowed connected devices.");
259 return HDF_ERR_IO;
260 }
261 if ((bstatus & HDMI_HDCP_BSTATUS_MAX_CASCADE_EXCEEDED_MARK) > 0) {
262 HDF_LOGE("hdcp auth, check bstatus, exceeds max allowed cascade.");
263 return HDF_ERR_IO;
264 }
265 return HDF_SUCCESS;
266 }
267
HdmiHdcpAuthenticationWaitKsvListReady(struct HdmiHdcp * hdcp)268 static int32_t HdmiHdcpAuthenticationWaitKsvListReady(struct HdmiHdcp *hdcp)
269 {
270 uint32_t i;
271 int32_t ret;
272 bool ready = false;
273
274 /* Set up 5s timer, poll for KSV list ready. Fail if timer expires prior to ready. */
275 for (i = 0; i < HDMI_HDCP_WAIT_KSV_LIST_READ_REG_CNT; i++) {
276 ret = HdmiHdcpRead(hdcp, HDMI_HDCP_BCAPS, &(hdcp->bcaps), sizeof(hdcp->bcaps));
277 if (ret != HDF_SUCCESS) {
278 return ret;
279 }
280 if ((hdcp->bcaps & HDMI_HDCP_BCAPS_KSV_FIFO_READY_MARK) > 0) {
281 ready = true;
282 break;
283 }
284 OsalMSleep(HDMI_HDCP_WAIT_KSV_LIST_READ_REG_INTERVAL);
285 }
286 if (ready == false) {
287 return HDF_ERR_TIMEOUT;
288 }
289
290 ret = HdmiHdcpAuthenticationCheckBstatus(hdcp);
291 if (ret != HDF_SUCCESS) {
292 return ret;
293 }
294 ret = HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_WRITE_BCAPS, &(hdcp->bcaps), sizeof(hdcp->bcaps));
295 if (ret != HDF_SUCCESS) {
296 HDF_LOGD("hdcp auth wait ksv list ready, WRITE_BCAPS fail");
297 }
298 ret = HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_WRITE_BSTATUS, hdcp->bstatus, sizeof(hdcp->bstatus));
299 if (ret != HDF_SUCCESS) {
300 HDF_LOGD("hdcp auth wait ksv list ready, WRITE_BSTATUS fail");
301 }
302 return HDF_SUCCESS;
303 }
304
HdmiHdcpAuthenticationReadKsvList(struct HdmiHdcp * hdcp)305 static int32_t HdmiHdcpAuthenticationReadKsvList(struct HdmiHdcp *hdcp)
306 {
307 int32_t ret;
308 uint32_t try = HDMI_HDCP_DEFAULT_READ_REG_TRY;
309
310 hdcp->ksvLen = HDMI_HDCP_GET_KSV_LEN(hdcp->deviceCount);
311 do {
312 ret = HdmiHdcpRead(hdcp, HDMI_HDCP_KSV_FIFO, hdcp->ksvList, hdcp->ksvLen);
313 if (ret == HDF_SUCCESS) {
314 break;
315 }
316 OsalMSleep(HDMI_HDCP_WAIT_KSV_LIST_READ_REG_INTERVAL);
317 try--;
318 } while (try > 0);
319
320 ret = HdmiHdcpReadMsgHv(hdcp);
321 if (ret != HDF_SUCCESS) {
322 return ret;
323 }
324 /* We may need to reset SHA before write ksv list. */
325 ret = HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_RESET_SHA, NULL, 0);
326 if (ret != HDF_SUCCESS) {
327 HDF_LOGD("hdcp auth read ksv list, RESET_SHA fail");
328 }
329 ret = HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_WRITE_KSV_FIFO, hdcp->ksvList, hdcp->ksvLen);
330 if (ret != HDF_SUCCESS) {
331 HDF_LOGD("hdcp auth read ksv list, WRITE_KSV_FIFO fail");
332 }
333 return HDF_SUCCESS;
334 }
335
HdmiHdcpAuthenticationSecondPart(struct HdmiHdcp * hdcp)336 static int32_t HdmiHdcpAuthenticationSecondPart(struct HdmiHdcp *hdcp)
337 {
338 int32_t ret;
339
340 /* Poll: KSV list ready. */
341 ret = HdmiHdcpAuthenticationWaitKsvListReady(hdcp);
342 if (ret != HDF_SUCCESS) {
343 HDF_LOGE("hdcp auth, wait ksv list ready fail.");
344 return ret;
345 }
346
347 /* Read KSV list */
348 ret = HdmiHdcpAuthenticationReadKsvList(hdcp);
349 if (ret != HDF_SUCCESS) {
350 HDF_LOGE("hdcp auth, read ksv list fail.");
351 return ret;
352 }
353
354 /* Verify V/V' matched or not */
355 ret = HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_CHECK_V, NULL, 0);
356 if (ret != HDF_SUCCESS) {
357 HDF_LOGE("hdcp auth, check V fail.");
358 return ret;
359 }
360 return HDF_SUCCESS;
361 }
362
HdmiHdcpAuthenticationSucc(struct HdmiHdcp * hdcp)363 static void HdmiHdcpAuthenticationSucc(struct HdmiHdcp *hdcp)
364 {
365 if (HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_AUTH_DONE, NULL, 0) != HDF_SUCCESS) {
366 HDF_LOGE("hdcp auth succ, AUTH_DONE fail.");
367 }
368 hdcp->state = HDMI_HDCP_AUTH_DONE;
369 hdcp->authRetryCnt = 0;
370 }
371
HdmiHdcpAuthenticationFail(struct HdmiHdcp * hdcp)372 static void HdmiHdcpAuthenticationFail(struct HdmiHdcp *hdcp)
373 {
374 if (HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_AUTH_FAIL, NULL, 0) != HDF_SUCCESS) {
375 HDF_LOGE("hdcp auth fail, AUTH_FAIL fail.");
376 }
377 hdcp->state = HDMI_HDCP_AUTH_FAIL;
378 }
379
HdmiHdcpAuthentication(struct HdmiHdcp * hdcp)380 static int32_t HdmiHdcpAuthentication(struct HdmiHdcp *hdcp)
381 {
382 int32_t ret;
383
384 if (hdcp == NULL || hdcp->priv == NULL) {
385 return HDF_ERR_INVALID_PARAM;
386 }
387
388 /* auth prepare, get aksv and driver clear registers. */
389 ret = HdmiHdcpAuthenticationPrepare(hdcp);
390 if (ret != HDF_SUCCESS) {
391 HdmiHdcpAuthenticationFail(hdcp);
392 return ret;
393 }
394
395 /*
396 * First part of the authentication exchange.
397 */
398 ret = HdmiHdcpAuthenticationFirstPart(hdcp);
399 if (ret != HDF_SUCCESS) {
400 HdmiHdcpAuthenticationFail(hdcp);
401 return ret;
402 }
403 HDF_LOGD("hdcp auth Part I success.");
404 /* receiver (0), repeater (1) */
405 if ((hdcp->bcaps & HDMI_HDCP_BCAPS_REPEATER_MARK) == 0) {
406 HdmiHdcpAuthenticationSucc(hdcp);
407 return ret;
408 }
409
410 /*
411 * The second part of the authentication protocol is required if the HDCP Reciever is an HDCP Repeater.
412 */
413 ret = HdmiHdcpAuthenticationSecondPart(hdcp);
414 if (ret != HDF_SUCCESS) {
415 HdmiHdcpAuthenticationFail(hdcp);
416 return ret;
417 }
418
419 HdmiHdcpAuthenticationSucc(hdcp);
420 return ret;
421 }
422
HdmiHdcpAuthenticationRetry(struct HdmiHdcp * hdcp)423 static int32_t HdmiHdcpAuthenticationRetry(struct HdmiHdcp *hdcp)
424 {
425 if (hdcp == NULL || hdcp->priv == NULL) {
426 return HDF_ERR_INVALID_PARAM;
427 }
428
429 if (hdcp->authRetryCnt > HDMI_HDCP_AUTH_MAX_RETRY_CNT) {
430 HDF_LOGE("hdcp auth reach to max cnt, auth fail");
431 return HDF_FAILURE;
432 }
433 return HdmiHdcpAuthentication(hdcp);
434 }
435
HdmiHdcpOpen(struct HdmiHdcp * hdcp)436 int32_t HdmiHdcpOpen(struct HdmiHdcp *hdcp)
437 {
438 int32_t ret;
439
440 (void)OsalMutexLock(&(hdcp->hdcpMutex));
441 hdcp->state = HDMI_HDCP_AUTH_INACTIVE;
442 hdcp->authRetryCnt = 0;
443 ret = HdmiHdcpAuthentication(hdcp);
444 if (ret == HDF_SUCCESS) {
445 HDF_LOGD("hdcp Authentication success!");
446 (void)OsalMutexUnlock(&(hdcp->hdcpMutex));
447 return ret;
448 }
449
450 while (hdcp->authRetryCnt <= HDMI_HDCP_AUTH_MAX_RETRY_CNT) {
451 ret = HdmiHdcpAuthenticationRetry(hdcp);
452 if (ret == HDF_SUCCESS) {
453 (void)OsalMutexUnlock(&(hdcp->hdcpMutex));
454 return ret;
455 }
456 hdcp->authRetryCnt++;
457 }
458 (void)OsalMutexUnlock(&(hdcp->hdcpMutex));
459 return ret;
460 }
461
HdmiHdcpClose(struct HdmiHdcp * hdcp)462 void HdmiHdcpClose(struct HdmiHdcp *hdcp)
463 {
464 if (hdcp == NULL) {
465 return;
466 }
467
468 if (hdcp->state == HDMI_HDCP_AUTH_INACTIVE ||
469 hdcp->state == HDMI_HDCP_AUTH_AKSV_INVALID) {
470 return;
471 }
472
473 if (HdmiHdcpWriteMsgToReg(hdcp, HDMI_HDCP_OPT_AUTH_CLOSE, NULL, 0) != HDF_SUCCESS) {
474 HDF_LOGD("hdcp close, AUTH_CLOSE fail");
475 }
476 hdcp->state = HDMI_HDCP_AUTH_INACTIVE;
477 hdcp->authRetryCnt = 0;
478 }
479