• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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