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