123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615 |
- #include "drv_types.h"
- #include <asm/io.h>
- #include "hdmi_hdcp.h"
- #include "../kmf/kmflib/bf.h"
- #include "drv_spi.h" /*spi_read_flash()*/
- #include <linux/slab.h> /*kmalloc(), kfree()*/
- #define HDCP_RAWKEY_SIZE (288)
- #define HDCP_CKEY_SIZE (512)
- #define HDCP_VKEY_SIZE (32)
- #define HDCP_RKEY_SIZE (40)
- #define HDCP_CRC_SIZE (4)
- #define HDCP_KEY_SIZE (HDCP_CKEY_SIZE+HDCP_VKEY_SIZE+HDCP_RKEY_SIZE)
- #ifdef CONFIG_SUPPORT_STORE_HDCP2X_TO_FLASH
- #define HDCP2X_RAWKEY_SIZE (898)
- #define HDCP2X_CKEY_SIZE (1024)
- #define HDCP2X_VKEY_SIZE (32)
- #define HDCP2X_RKEY_SIZE (40)
- #define HDCP2X_CRC_SIZE (4)
- #define HDCP2X_KEY_SIZE (HDCP2X_CKEY_SIZE+HDCP2X_VKEY_SIZE+HDCP2X_RKEY_SIZE)
- #define HDCP2X_HEADER_SIZE (4)
- #define HDCP2X_LIC_CONST_SIZE (36) //Licensed Constant
- #define HDCP2X_PUB_CERT_SIZE (522) //Public Certificate
- #define HDCP2X_PVT_KEY_SIZE (340) //Private Key
- #endif
- //debug message
- //#define SUPPORT_PRINT_HDCP_MESSAGE
- // ----- local static variables/functions -----
- #pragma pack(push,1)
- typedef struct __HDCPKEY_FMT
- {
- union
- {
- UINT32 data[(HDCP_KEY_SIZE/4)];
- struct
- {
- UINT8 ckey[HDCP_CKEY_SIZE];
- UINT8 vkey[HDCP_VKEY_SIZE];
- UINT8 rkey[HDCP_RKEY_SIZE];
- };
- };
- UINT32 crc;
- } HDCPKEY_FMT, *HDCPKEY_FMT_PTR;
- #ifdef CONFIG_SUPPORT_STORE_HDCP2X_TO_FLASH
- typedef struct __HDCP2X_KEY_FMT
- {
- union
- {
- UINT32 data[(HDCP2X_KEY_SIZE/4)];
- struct
- {
- UINT8 ckey[HDCP2X_CKEY_SIZE];
- UINT8 vkey[HDCP2X_VKEY_SIZE];
- UINT8 rkey[HDCP2X_RKEY_SIZE];
- };
- };
- UINT32 crc;
- } HDCP2X_KEY_FMT, *HDCP2X_KEY_FMT_PTR;
- typedef struct __HDCP2X_REV_KEY_SET
- {
- struct
- {
- UINT8 Header[HDCP2X_HEADER_SIZE];
- UINT8 LicConst[HDCP2X_LIC_CONST_SIZE];
- UINT8 PubCert[HDCP2X_PUB_CERT_SIZE];
- UINT8 PvtKey[HDCP2X_PVT_KEY_SIZE];
- };
- } HDCP2X_REV_KEY_SET, *HDCP2X_REV_KEY_SET_PTR;
- #endif
- #pragma pack(pop)
- static BOOL bHDCP_CRC = false;
- static UINT8 local_ksv[5];
- static UINT8 local_key_data[HDCP_RAWKEY_SIZE];
- #ifdef CONFIG_SUPPORT_STORE_HDCP2X_TO_FLASH
- static UINT8 local_2Xkey_data[HDCP2X_RAWKEY_SIZE];
- #endif
- #ifdef CONFIG_DISABLE_CIKEY_HDCPKEY_SPI_ENCRYPT
- extern void do_spi_encrypt(char *, unsigned int, unsigned int);
- #endif
- #ifdef SUPPORT_PRINT_HDCP_MESSAGE
- static void dump(const UINT8 *ptr, INT32 size)
- {
- INT32 i, n;
- INT8 str[3 * 0x10 + 8];
- for (n = 0, i = 0; i < size; i++)
- {
- if (n >= 0)
- {
- n += sprintf(&str[n], "%02x ", ptr[i]);
- }
- if (n >= 3 * 0x10 || i + 1 == size)
- {
- n = 0;
- printk("%s\n", str);
- }
- }
- }
- #endif
- /* Keep the encrypt functions for future use */
- #if 0
- static void cmN_arraBye_shift_inc(INT8 *pChar, INT32 byteLen, INT32 bitShift)
- {
- //limit 1024 byte
- UINT8 *pBye;
- UINT8 pBAck[1024];
- INT32 i;
- INT32 offByte, offBit;
- ULONG tempDW;
- pBye = (UINT8 *)pChar;
- if (byteLen > 1024)
- {
- return;
- }
- offByte = bitShift / 8;
- offByte = offByte % byteLen;
- offBit = bitShift & 0x07;//%8
- if (offByte)
- {
- memcpy(pBAck, pBye, byteLen);
- for (i = 0; i < byteLen ; i++)
- {
- if ((i + offByte) < byteLen)
- {
- pBye[i + offByte] = pBAck[i];
- }
- else
- {
- pBye[i + offByte - byteLen] = pBAck[i];
- }
- }
- }
- if (offBit)
- {
- memcpy(pBAck, pBye, byteLen);
- for (i = 0; i < byteLen ; i++)
- {
- if (i == 0)
- {
- tempDW = (((UINT32)pBAck[0]) << 8) + pBAck[byteLen - 1];
- }
- else
- {
- tempDW = (((UINT32)pBAck[i]) << 8) + pBAck[i - 1];
- }
- tempDW = tempDW >> (8 - offBit);
- pBye[i] = (UINT8)tempDW;
- }
- }
- }
- static void byteEncryption(UINT8 *pByte, INT32 length)
- {
- UINT8 seed1, seed2, seed3;
- INT32 i;
- UINT8 temp1, temp2;
- UINT8 temp3, temp4;
- UINT8 temp5, temp6;
- UINT8 tt;
- if (length > 4)
- {
- pByte[1] = (pByte[1] + pByte[0]) & 0xff;
- pByte[length - 2] = (pByte[length - 2] + pByte[length - 1]) & 0xff;
- cmN_arraBye_shift_inc((INT8 *)(pByte + 1), (length - 2), (INT32)(((pByte[0] + pByte[length - 1])) * 19) & 0xff);
- }
- tt = 0x98;
- for (i = 0; i < length; i++)
- {
- *(pByte + i) = (*(pByte + i)) ^ tt;
- tt++;
- }
- seed1 = 0xee;
- seed2 = 0x5A;
- seed3 = 0x63;
- for (i = 0; i < length; i++)
- {
- *(pByte + i) = (*(pByte + i)) ^ seed1;
- }
- if (length > 2)
- {
- for (i = 0; i < length / 2; i++)
- {
- //1234 to 41 23
- temp1 = (*(pByte + i)) & 0xF0;
- temp2 = (*(pByte + i)) & 0x0F;
- temp3 = (*(pByte + i + (length / 2))) & 0xF0;
- temp4 = (*(pByte + i + (length / 2))) & 0x0F;
- (*(pByte + i)) = (temp4 << 4) | (temp1 >> 4);
- (*(pByte + i + (length / 2))) = (temp2 << 4) | (temp3 >> 4);
- }
- }
- for (i = 0; i < length; i++)
- {
- *(pByte + i) = (*(pByte + i)) ^ seed2;
- }
- tt = 0x6c;
- for (i = 0; i < length; i++)
- {
- *(pByte + i) = (*(pByte + i)) ^ tt;
- tt += 0xf9;
- }
- if (length > 3)
- {
- for (i = 0; i < length / 3; i++)
- {
- //123456 to 54 16 32
- temp1 = (*(pByte + i)) & 0xF0;
- temp2 = (*(pByte + i)) & 0x0F;
- temp3 = (*(pByte + i + (length / 3) * 1)) & 0xF0;
- temp4 = (*(pByte + i + (length / 3) * 1)) & 0x0F;
- temp5 = (*(pByte + i + (length / 3) * 2)) & 0xF0;
- temp6 = (*(pByte + i + (length / 3) * 2)) & 0x0F;
- (*(pByte + i)) = (temp5) | (temp4);
- (*(pByte + i + (length / 3) * 1)) = (temp1) | (temp6);
- (*(pByte + i + (length / 3) * 2)) = (temp3) | (temp2);
- }
- }
- for (i = 0; i < length; i++)
- {
- *(pByte + i) = (*(pByte + i)) ^ seed3;
- }
- }
- #endif
- static void cmN_arraBye_shift_dec(INT8 *pChar, INT32 byteLen, INT32 bitShift)
- {
- //limit 1024 byte
- UINT8 *pBye;
- INT32 i;
- INT32 offByte, offBit;
- ULONG tempDW;
- UINT8 *pBAck = kmalloc(1024, GFP_KERNEL);
- pBye = (UINT8*)pChar;
- if (pBAck == NULL)
- {
- return;
- }
- if (byteLen > 1024)
- {
- kfree(pBAck) ;
- return;
- }
- offByte = bitShift / 8;
- offByte = offByte % byteLen;
- offBit = bitShift & 0x07;//%8
- if (offByte)
- {
- memcpy(pBAck, pBye, byteLen);
- for (i = 0; i < byteLen ; i++)
- {
- if ((i + offByte) < byteLen)
- {
- pBye[i] = pBAck[i + offByte];
- }
- else
- {
- pBye[i] = pBAck[i + offByte - byteLen];
- }
- }
- }
- if (offBit)
- {
- memcpy(pBAck, pBye, byteLen);
- for (i = 0; i < byteLen ; i++)
- {
- if (i == byteLen - 1)
- {
- tempDW = (((UINT32)pBAck[0]) << 8) + pBAck[byteLen - 1];
- }
- else
- {
- tempDW = (((UINT32)pBAck[i + 1]) << 8) + pBAck[i];
- }
- tempDW = tempDW >> offBit;
- pBye[i] = (UINT8)tempDW;
- }
- }
- kfree(pBAck) ;
- }
- static void byteDecryption(UINT8 *pByte, INT32 length)
- {
- UINT8 seed1, seed2, seed3;
- INT32 i;
- UINT8 temp1, temp2;
- UINT8 temp3, temp4;
- UINT8 temp5, temp6;
- UINT8 tt;
- seed1 = 0xee;
- seed2 = 0x5A;
- seed3 = 0x63;
- for (i = 0; i < length; i++)
- {
- *(pByte + i) = (*(pByte + i)) ^ seed3;
- }
- if (length > 3)
- {
- for (i = 0; i < length / 3; i++)
- {
- //123456 to 54 16 32
- temp5 = (*(pByte + i)) & 0xF0;
- temp4 = (*(pByte + i)) & 0x0F;
- temp1 = (*(pByte + i + (length / 3) * 1)) & 0xF0;
- temp6 = (*(pByte + i + (length / 3) * 1)) & 0x0F;
- temp3 = (*(pByte + i + (length / 3) * 2)) & 0xF0;
- temp2 = (*(pByte + i + (length / 3) * 2)) & 0x0F;
- (*(pByte + i)) = (temp1) | (temp2);
- (*(pByte + i + (length / 3) * 1)) = (temp3) | (temp4);
- (*(pByte + i + (length / 3) * 2)) = (temp5) | (temp6);
- }
- }
- tt = 0x6c;
- for (i = 0; i < length; i++)
- {
- *(pByte + i) = (*(pByte + i)) ^ tt;
- tt += 0xf9;
- }
- for (i = 0; i < length; i++)
- {
- *(pByte + i) = (*(pByte + i)) ^ seed2;
- }
- if (length > 2)
- {
- for (i = 0; i < length / 2; i++)
- {
- //1234 to 41 23
- temp4 = (*(pByte + i)) & 0xF0;
- temp1 = (*(pByte + i)) & 0x0F;
- temp2 = (*(pByte + i + (length / 2))) & 0xF0;
- temp3 = (*(pByte + i + (length / 2))) & 0x0F;
- (*(pByte + i)) = (temp1 << 4) | (temp2 >> 4);
- (*(pByte + i + (length / 2))) = (temp3 << 4) | (temp4 >> 4);
- }
- }
- for (i = 0; i < length; i++)
- {
- *(pByte + i) = (*(pByte + i)) ^ seed1;
- }
- tt = 0x98;
- for (i = 0; i < length; i++)
- {
- *(pByte + i) = (*(pByte + i)) ^ tt;
- tt++;
- }
- if (length > 4)
- {
- cmN_arraBye_shift_dec((INT8 *)(pByte + 1), (length - 2), (INT32)(((pByte[0] + pByte[length - 1])) * 19) & 0xff);
- pByte[length - 2] = (pByte[length - 2] - pByte[length - 1]) & 0xff;
- pByte[1] = (pByte[1] - pByte[0]) & 0xff;
- }
- }
- static void henx(UINT8* key_addr)
- {
- UINT8* dk_addr = key_addr + 8;
- UINT8 xor_bytes[7] =
- {
- 0x4a, 0x65, 0x67, 0x72, 0x6f, 0x65, 0x47
- };
- UINT8 map[40] =
- {
- 17, 36, 12, 29, 21, 10, 18, 37, 31, 1 ,
- 2, 23, 35, 7, 27, 39, 3, 16, 8, 33,
- 28, 25, 6, 14, 13, 4, 0, 20, 30, 9 ,
- 5, 32, 38, 11, 15, 26, 19, 22, 34, 24
- };
- UINT8 temp[280];
- INT32 i = 0, j = 0;
- for (i = 0; i < 40; i++)
- {
- for (j = 0; j < 7; j++)
- {
- temp[map[i] * 7 + j] = dk_addr[i * 7 + j] ^ xor_bytes[j];
- }
- }
- memcpy(dk_addr, temp, 280);
- }
- #ifdef CONFIG_SUPPORT_STORE_HDCP2X_TO_FLASH
- static INT32 xcrypt_HDCP2X(UINT8 *in, UINT8 *out, UINT32 len)
- {
- // input 1024-byte HDCP encoded data, output 898-byte HDCP key.
- UINT32 SAMPLE_KEY1_DW = 0x01234567;
- UINT32 SAMPLE_KEY2_DW = 0x89abcdef;
- INT32 i = 0;
- UINT8 pInSeed[sizeof(ULONG)];
- memcpy(pInSeed, &SAMPLE_KEY1_DW, sizeof(ULONG));
- for (i = 0 ; i < 36 ; i++)
- {
- *(out + i) = *(in + i) ^ pInSeed[i % 4];
- }
- memcpy(pInSeed, &SAMPLE_KEY2_DW, sizeof(ULONG));
- for (i = 36 ; i < 898 ; i++)
- {
- *(out + i) = *(in + i) ^ pInSeed[i % 4];
- }
- return 0;
- }
- #endif
- static INT32 xcrypt(UINT8 *in, UINT8 *out, UINT32 len)
- {
- // input 512-byte HDCP encoded data, output 288-byte HDCP key.
- UINT32 SAMPLE_KEY1_DW = 0x01234567;
- UINT32 SAMPLE_KEY2_DW = 0x89abcdef;
- INT32 i = 0;
- UINT8 pInSeed[sizeof(ULONG)];
- memcpy(pInSeed, &SAMPLE_KEY1_DW, sizeof(ULONG));
- for (i = 0 ; i < 5 ; i++)
- {
- *(out + i) = *(in + i) ^ pInSeed[i % 4];
- }
- memcpy(pInSeed, &SAMPLE_KEY2_DW, sizeof(ULONG));
- for (i = 8 ; i < 288 ; i++)
- {
- *(out + i) = *(in + i) ^ pInSeed[i % 4];
- }
- return 0;
- }
- UINT32 hdmi_get_hdcp_data(INT32 offset)
- {
- UINT32 *data = (UINT32*)local_key_data;
- return data[offset];
- }
- BOOL DRV_HDMI_CheckHdcpKey(void)
- {
- return bHDCP_CRC;
- }
- void DRV_HDMI_GetHDCPKeyKSV(UINT8 *ksv)
- {
- memcpy(ksv, &local_ksv, 5);
- }
- void DRV_HDMI_UpdateHDCPKey(UINT8 *key_ptr)
- {
- INT32 i;
- UINT32 calculated_crc;
- UINT8 *pbHdcpKey;
- HDCPKEY_FMT_PTR key;
- #ifdef CONFIG_DISABLE_CIKEY_HDCPKEY_SPI_ENCRYPT
- UINT8 *pbHdcpKey_tmp;
- #endif
- pbHdcpKey = kmalloc(sizeof(UINT8) * (HDCP_KEY_SIZE+HDCP_CRC_SIZE), GFP_KERNEL);
- spi_read_flash(pbHdcpKey, (UINT8*)key_ptr, (HDCP_KEY_SIZE+HDCP_CRC_SIZE));
- #ifdef CONFIG_DISABLE_CIKEY_HDCPKEY_SPI_ENCRYPT
- pbHdcpKey_tmp = kmalloc((((HDCP_KEY_SIZE+HDCP_CRC_SIZE+15)>>4)<<4), GFP_KERNEL);
- memcpy((void *)pbHdcpKey_tmp, (void *)pbHdcpKey, (HDCP_KEY_SIZE+HDCP_CRC_SIZE));
- do_spi_encrypt((INT8 *)pbHdcpKey_tmp, (((HDCP_KEY_SIZE+HDCP_CRC_SIZE+15)>>4)<<4), 0);
- memcpy((void *)pbHdcpKey, (void *)pbHdcpKey_tmp, (HDCP_KEY_SIZE+HDCP_CRC_SIZE));
- kfree(pbHdcpKey_tmp);
- #endif
- key = (HDCPKEY_FMT_PTR)pbHdcpKey;
- /* Input data is encrypted and decryption needed */
- calculated_crc = 0;
- for (i = 0; i < (HDCP_KEY_SIZE/4); i++)
- {
- calculated_crc += (UINT32)key->data[i];
- }
- bHDCP_CRC = (calculated_crc == key->crc) ? 1 : 0;
- byteDecryption(key->vkey, HDCP_VKEY_SIZE);
- byteDecryption(key->rkey, HDCP_RKEY_SIZE);
- bf_decrypt(key->ckey, HDCP_CKEY_SIZE, key->rkey, HDCP_RKEY_SIZE);
- xcrypt(key->ckey, key->ckey, HDCP_CKEY_SIZE);
- /* Update local ksv data */
- memcpy(local_ksv, key->ckey, 5);
- /* Update to local key data */
- memcpy(local_key_data, key->ckey, HDCP_RAWKEY_SIZE);
- #ifdef SUPPORT_PRINT_HDCP_MESSAGE
- printk("hdcp raw key\n");
- dump(local_key_data, HDCP_RAWKEY_SIZE);
- #endif
-
- /* Transform raw hdcp key into hw format */
- henx(local_key_data);
- #ifdef SUPPORT_PRINT_HDCP_MESSAGE
- printk("henx\n");
- dump(local_key_data, HDCP_RAWKEY_SIZE);
- #endif
- kfree(pbHdcpKey);
- }
- #ifdef CONFIG_SUPPORT_STORE_HDCP2X_TO_FLASH
- void DRV_HDMI_UpdateHDCP2XKey(UINT8 *key_ptr)
- {
- INT32 i;
- UINT32 calculated_crc;
- UINT8 *pbHdcpKey;
- HDCP2X_KEY_FMT_PTR key;
- HDCP2X_REV_KEY_SET Hdcp2X_Key;
- #ifdef CONFIG_DISABLE_CIKEY_HDCPKEY_SPI_ENCRYPT
- UINT8 *pbHdcpKey_tmp;
- #endif
- pbHdcpKey = kmalloc(sizeof(UINT8) * (HDCP2X_KEY_SIZE+HDCP2X_CRC_SIZE), GFP_KERNEL);
- spi_read_flash(pbHdcpKey, (UINT8*)key_ptr, (HDCP2X_KEY_SIZE+HDCP2X_CRC_SIZE));
- #ifdef CONFIG_DISABLE_CIKEY_HDCPKEY_SPI_ENCRYPT
- pbHdcpKey_tmp = kmalloc((((HDCP2X_KEY_SIZE+HDCP2X_CRC_SIZE+15)>>4)<<4), GFP_KERNEL);
- memcpy((void *)pbHdcpKey_tmp, (void *)pbHdcpKey, (HDCP2X_KEY_SIZE+HDCP2X_CRC_SIZE));
- do_spi_encrypt((INT8 *)pbHdcpKey_tmp, (((HDCP2X_KEY_SIZE+HDCP2X_CRC_SIZE+15)>>4)<<4), 0);
- memcpy((void *)pbHdcpKey, (void *)pbHdcpKey_tmp, (HDCP2X_KEY_SIZE+HDCP2X_CRC_SIZE));
- kfree(pbHdcpKey_tmp);
- #endif
- key = (HDCP2X_KEY_FMT_PTR)pbHdcpKey;
- /* Input data is encrypted and decryption needed */
- calculated_crc = 0;
- for (i = 0; i < (HDCP2X_KEY_SIZE/4); i++)
- {
- calculated_crc += (UINT32)key->data[i];
- }
- bHDCP_CRC = (calculated_crc == key->crc) ? 1 : 0;
- byteDecryption(key->vkey, HDCP2X_VKEY_SIZE);
- byteDecryption(key->rkey, HDCP2X_RKEY_SIZE);
- bf_decrypt(key->ckey, HDCP2X_CKEY_SIZE, key->rkey, HDCP2X_RKEY_SIZE);
- xcrypt_HDCP2X(key->ckey, key->ckey, HDCP2X_CKEY_SIZE);
- /* Update to local key data */
- memcpy(local_2Xkey_data, key->ckey, HDCP2X_RAWKEY_SIZE);
- #ifdef SUPPORT_PRINT_HDCP_MESSAGE
- printk("hdcp2X raw key\n");
- dump(local_2Xkey_data, HDCP2X_RAWKEY_SIZE);
- #endif
- Hdcp2X_Key.Header[0]=0x00;
- Hdcp2X_Key.Header[1]=0x00;
- Hdcp2X_Key.Header[2]=0x00;
- Hdcp2X_Key.Header[3]=0x02;
- memcpy(Hdcp2X_Key.LicConst, &(key->ckey[0]), HDCP2X_LIC_CONST_SIZE);
- memcpy(Hdcp2X_Key.PubCert, &(key->ckey[36]), HDCP2X_PUB_CERT_SIZE);
- memcpy(Hdcp2X_Key.PvtKey, &(key->ckey[558]), HDCP2X_PVT_KEY_SIZE);
- #ifdef SUPPORT_PRINT_HDCP_MESSAGE
- printk("hdcp2X key header\n");
- dump(Hdcp2X_Key.Header, 4);
- printk("hdcp2X key Licensed Constant\n");
- dump(Hdcp2X_Key.LicConst, HDCP2X_LIC_CONST_SIZE);
- printk("hdcp2X key Public Certificate\n");
- dump(Hdcp2X_Key.PubCert, HDCP2X_PUB_CERT_SIZE);
- printk("hdcp2X key Private Key\n");
- dump(Hdcp2X_Key.PvtKey, HDCP2X_PVT_KEY_SIZE);
- #endif
- kfree(pbHdcpKey);
- }
- #endif
|