| /* |
| * \file km_secure_key.c |
| * \brief secure storage key ops for key manage |
| * |
| * \version 1.0.0 |
| * \date 15/06/30 |
| * \author Sam.Wu <yihui.wu@amlgic.com> |
| * |
| * Copyright (c) 2015 Amlogic. All Rights Reserved. |
| * |
| */ |
| #include "key_manage_i.h" |
| #include <amlogic/amlkey_if.h> |
| #include <u-boot/sha256.h> |
| |
| int keymanage_securekey_init(const char* buf, int len) |
| { |
| int encrypt_type; |
| |
| encrypt_type = unifykey_get_encrypt_type(); |
| return amlkey_init((uint8_t*)buf, len, encrypt_type); //confirm |
| } |
| |
| int keymanage_securekey_exit(void) |
| { |
| return 0; |
| } |
| |
| int keymanage_secukey_write(const char *keyname, const void* keydata, unsigned int datalen) |
| { |
| int ret = 0; |
| uint8_t origSum[SHA256_SUM_LEN]; |
| const int isSecure = ( KEY_M_SECURE_KEY == keymanage_dts_get_key_device(keyname) ) ? 1 : 0; |
| const int isEncrypt= strlen(keymanage_dts_get_enc_type(keyname)) ? 1 : 0; |
| const unsigned int keyAttr = ( isSecure << 0 ) | ( isEncrypt << 8 ); |
| ssize_t writenLen = 0; |
| |
| if (isSecure) |
| { |
| sha256_context ctx; |
| sha256_starts(&ctx); |
| sha256_update(&ctx, keydata, datalen); |
| sha256_finish(&ctx, origSum); |
| } |
| |
| KM_MSG("isEncrypt=%s\n", keymanage_dts_get_enc_type(keyname)); |
| KM_DBG("%s, keyname=%s, keydata=%p, datalen=%d, isSecure=%d\n", __func__, keyname, keydata, datalen, isSecure); |
| KM_MSG("keyAttr is 0x%08X\n", keyAttr); |
| writenLen = amlkey_write((uint8_t*)keyname, (uint8_t*)keydata, datalen, keyAttr); |
| if (writenLen != datalen) { |
| KM_ERR("Want to write %u bytes, but only %zd Bytes\n", datalen, writenLen); |
| return __LINE__; |
| } |
| |
| if (isSecure) |
| { |
| uint8_t genSum[SHA256_SUM_LEN]; |
| |
| ret = amlkey_hash_4_secure((uint8_t*)keyname, genSum); |
| if (ret) { |
| KM_ERR("Failed when gen hash for secure key[%s], ret=%d\n", keyname, ret); |
| return __LINE__; |
| } |
| |
| ret = memcmp(origSum, genSum, SHA256_SUM_LEN); |
| if (ret) |
| { |
| int index = 0; |
| char origSum_str[SHA256_SUM_LEN * 2 + 2]; |
| char genSum_str[SHA256_SUM_LEN * 2 + 2]; |
| |
| origSum_str[0] = genSum_str[0] = '\0'; |
| for (index = 0; index < SHA256_SUM_LEN; ++index) { |
| |
| sprintf(origSum_str, "%s%02x", origSum_str, origSum[index]); |
| sprintf(genSum_str, "%s%02x", genSum_str, genSum[index]); |
| } |
| |
| KM_ERR("Failed in check hash, origSum[%s] != genSum[%s]\n", origSum_str, genSum_str); |
| return __LINE__; |
| } |
| KM_MSG("OK in check sha1256 in burn key[%s]\n", keyname); |
| } |
| |
| return ret; |
| } |
| |
| ssize_t keymanage_secukey_size(const char* keyname) |
| { |
| return amlkey_size((uint8_t*)keyname); //actully size |
| } |
| |
| int keymanage_secukey_exist(const char* keyname) |
| { |
| return amlkey_isexsit((uint8_t*)keyname); //exsit 1, non 0 |
| } |
| |
| int keymanage_secukey_can_read(const char* keyname) |
| { |
| return !amlkey_issecure((uint8_t*)keyname); //secure 1, non 0 |
| } |
| |
| int keymanage_secukey_read(const char* keyname, void* databuf, unsigned buflen) |
| { |
| int ret = 0; |
| |
| ret = keymanage_secukey_can_read(keyname); |
| if (!ret) { |
| KM_ERR("key[%s] can't read, is configured secured?\n", keyname); |
| return __LINE__; |
| } |
| |
| const ssize_t readLen = amlkey_read((uint8_t*)keyname, (uint8_t*)databuf, buflen); |
| if (readLen != buflen) { |
| KM_ERR("key[%s], want read %u Bytes, but %zd bytes\n", keyname, buflen, readLen); |
| return __LINE__; |
| } |
| |
| return 0; |
| } |
| |
| #if 1//hdcp2 rx start |
| #define HDCP2_RX_LC128_LEN (36) |
| #define HDCP2_RX_KEY_LEN (862) |
| #pragma pack(push, 1) |
| typedef struct _Hdcp2RxKeyFmt{ |
| unsigned version; |
| char lc128[HDCP2_RX_LC128_LEN]; |
| char keyVal[HDCP2_RX_KEY_LEN]; |
| }Hdcp2RxKeyFmt_t; |
| #pragma pack(pop) |
| |
| #define HDCP2_RX_KEY_TOTAL_LEN sizeof(Hdcp2RxKeyFmt_t) |
| #define HDCP2_RX_KEY_LC128_NAME "hdcp2lc128" |
| #define HDCP2_RX_KEY_NAME "hdcp2key" |
| #define HDCP2_RX_KEY_VERSION (0x02000000U) |
| #define HDCP2_VERSION_LEN ( 4 ) |
| |
| static char generalDataChange(const char input) |
| { |
| int i; |
| char result = 0; |
| |
| for (i=0; i<8; i++) { |
| if ((input & (1<<i)) != 0) |
| result |= (1<<(7-i)); |
| else |
| result &= ~(1<<(7-i)); |
| } |
| |
| return result; |
| } |
| |
| static void hdcp2DataEncryption(const unsigned len, const char *input, char *out) |
| { |
| int i = 0; |
| |
| for (i=0; i<len; i++) |
| *out++ = generalDataChange(*input++); |
| } |
| |
| static void hdcp2DataDecryption(const unsigned len, const char *input, char *out) |
| { |
| int i = 0; |
| |
| for (i=0; i<len; i++) |
| *out++ = generalDataChange(*input++); |
| } |
| |
| int _burn_key_in_type_hdcp2(const char* keyname, void* databuf, const unsigned bufLen, char* decryptBuf) |
| { |
| Hdcp2RxKeyFmt_t* pHdcp2RxKey = (Hdcp2RxKeyFmt_t*)databuf; |
| const int keyLen = HDCP2_RX_KEY_TOTAL_LEN; |
| |
| if (keyLen > bufLen) { |
| KM_ERR("hdcp2 rx len unsupported. want %d but get %d\n", keyLen, bufLen); |
| return __LINE__; |
| } |
| if (HDCP2_RX_KEY_VERSION != pHdcp2RxKey->version) { |
| KM_ERR("Version value 0x%x is error, should be 0x%x\n", pHdcp2RxKey->version, HDCP2_RX_KEY_VERSION); |
| return __LINE__; |
| } |
| |
| hdcp2DataEncryption(keyLen, databuf, decryptBuf); |
| KM_MSG("Ecnrypt hdcp2 END.\n"); |
| pHdcp2RxKey = (Hdcp2RxKeyFmt_t*)decryptBuf; |
| |
| const uint8_t* tmpName = (uint8_t*)HDCP2_RX_KEY_LC128_NAME; |
| unsigned tmpLen = HDCP2_RX_LC128_LEN; |
| unsigned isSecure = 0; |
| ssize_t retLen = 0; |
| retLen = amlkey_write(tmpName, (uint8_t*)&pHdcp2RxKey->lc128, tmpLen , isSecure); |
| if (retLen != tmpLen) { |
| KM_ERR ("Fail in write hdcp2 lc128, retLen %zd != want len %d\n", retLen, tmpLen) ; |
| return __LINE__; |
| } |
| |
| tmpName = (uint8_t*)HDCP2_RX_KEY_NAME; |
| tmpLen = HDCP2_RX_KEY_LEN; |
| retLen = amlkey_write(tmpName, (uint8_t*)&pHdcp2RxKey->keyVal, tmpLen , isSecure); |
| if (retLen != tmpLen) { |
| KM_ERR ("Fail in write hdcp2 key, retLen %zd != want len %d\n", retLen, tmpLen) ; |
| return __LINE__; |
| } |
| |
| tmpLen = HDCP2_VERSION_LEN; |
| retLen = amlkey_write((uint8_t*)keyname, (uint8_t*)&pHdcp2RxKey->version, tmpLen, isSecure); |
| if (retLen != tmpLen) { |
| KM_ERR ("Fail in write hdcp2 key, retLen %zd != want len %d\n", retLen, tmpLen) ; |
| return __LINE__; |
| } |
| |
| return 0; |
| } |
| |
| int _read_key_in_type_hdcp2(const char* keyname, void* databuf, const unsigned bufLen, char* decryptBuf) |
| { |
| const unsigned srcKeyLen = HDCP2_RX_KEY_TOTAL_LEN; |
| Hdcp2RxKeyFmt_t* pHdcp2RxKey = (Hdcp2RxKeyFmt_t*)decryptBuf; |
| const uint8_t* tmpName = NULL; |
| int tmpLen = 0; |
| |
| if (bufLen < srcKeyLen) { |
| KM_ERR("hdcp2 rx len unsupported. want %d but only %d\n", srcKeyLen, bufLen); |
| return __LINE__; |
| } |
| |
| ssize_t retLen = 0; |
| tmpName = (uint8_t*)keyname; |
| tmpLen = HDCP2_VERSION_LEN; |
| retLen = amlkey_read(tmpName, (uint8_t*)&pHdcp2RxKey->version, tmpLen); |
| if (retLen != tmpLen) { |
| KM_ERR ("Fail in read key[%s] at len %d\n", tmpName, tmpLen) ; |
| return __LINE__; |
| } |
| |
| tmpName = (uint8_t*)HDCP2_RX_KEY_NAME; |
| tmpLen = HDCP2_RX_KEY_LEN; |
| retLen = amlkey_read(tmpName, (uint8_t*)&pHdcp2RxKey->keyVal, tmpLen); |
| if (retLen != tmpLen) { |
| KM_ERR ("Fail in read key[%s] at len %d\n", tmpName, tmpLen) ; |
| return __LINE__; |
| } |
| |
| tmpName = (uint8_t*)HDCP2_RX_KEY_LC128_NAME; |
| tmpLen = HDCP2_RX_LC128_LEN; |
| retLen = amlkey_read(tmpName, (uint8_t*)&pHdcp2RxKey->lc128, tmpLen); |
| if (retLen != tmpLen) { |
| KM_ERR ("Fail in read key[%s] at len %d\n", tmpName, tmpLen) ; |
| return __LINE__; |
| } |
| |
| hdcp2DataDecryption(srcKeyLen, (char*)pHdcp2RxKey, databuf); |
| |
| return 0; |
| } |
| int _km_hdcp2_size(void) |
| { |
| return HDCP2_RX_KEY_TOTAL_LEN; |
| } |
| #endif//hdcp2 rx end |
| |
| |