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