| /* |
| * \file sdc_keysprovider.c |
| * \brief Parse users' nankey/efusekey like PC's keysprovider.dll in sdcard burning mode |
| * |
| * \version 1.0.0 |
| * \date 2014/12/25 |
| * \author Sam.Wu <yihui.wu@amlgic.com> |
| * |
| * Copyright (c) 2014 Amlogic. All Rights Reserved. |
| * |
| */ |
| #include "../optimus_sdc_burn_i.h" |
| #include "sdc_bootPart_license.h" |
| |
| #define _KEYS_PRV_DBG(fmt...) //DWN_MSG(fmt) |
| #define _KEYS_PRV_ITEM_INF_ADDR_4_CONSIST (OPTIMUS_DOWNLOAD_DISPLAY_BUF + 48 * 1024) |
| #define _KEYS_PRV_ITEM_INF_ADDR_MISC (OPTIMUS_DOWNLOAD_DISPLAY_BUF + 52 * 1024) |
| |
| #define _KEY_VAL_TMP_BUF (OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR - OPTIMUS_DOWNLOAD_SLOT_SZ) |
| static struct { |
| char* keyBuf; |
| unsigned keySize; |
| }_currentKey = {0}; |
| |
| //Note: keys which read only is not need to update license, and so not need stored in boot partition |
| //Typedef for keys structs in sdcard boot partition |
| #if 1 |
| #define AML_BOOT_PART_KEY_IMG_OFFSET (0X2U<<20) |
| #define AML_BOOT_PART_KEY_IMG_MAGIC_LEN 8 |
| #define AML_BOOT_PART_KEY_IMG_MAGIC_V1 "AML_KEY!" |
| #define AML_BOOT_PART_KEY_IMG_ALIGN_SZ 512 |
| #define AML_BOOT_PART_KEY_IMG_HEAD_SZ (64) |
| |
| #define AML_BOOT_PART_KEY_ITEM_INF_LEN (64) |
| #define AML_BOOT_PART_KEY_ITEM_NAME_LEN_MAX (16) |
| |
| //struct for the keys head which stored in boot partition |
| #pragma pack(push, 4) |
| typedef struct { |
| __u32 crc; |
| __s32 version; |
| |
| __u8 magic[AML_BOOT_PART_KEY_IMG_MAGIC_LEN]; |
| |
| __u32 imgSz; |
| __u32 imgItemNum; |
| |
| __u32 alignSz;//512 |
| __u8 resrv[AML_BOOT_PART_KEY_IMG_HEAD_SZ - 8 * 3 - 4]; |
| |
| }AmlBootPartKeysHead_t; |
| #pragma pack(pop) |
| |
| #pragma pack(push, 4) |
| typedef struct { |
| __u8 keyName[AML_BOOT_PART_KEY_ITEM_NAME_LEN_MAX]; |
| |
| __u32 itemIndex; |
| __u32 itemSz; //equl to sizeof of each key |
| |
| __u32 itemBodyOffset; |
| __u32 itemHasConf;//this item name is configured in keys.conf |
| |
| __u8 resrv[32]; |
| |
| }KeyInfo_t; |
| #pragma pack(pop) |
| |
| #define MAX_KEY_INF_NUM 5 //the max key numbers supported at the same time |
| |
| typedef struct { |
| AmlBootPartKeysHead_t bootPartKeyHead; |
| KeyInfo_t keysInf[MAX_KEY_INF_NUM]; |
| }BootPartKeyInf_t; |
| |
| #endif//image for keys END #if 1 |
| |
| #define debugP(fmt...) //printf("L%d:", __LINE__),printf(fmt) |
| #define errorP(fmt...) printf("Err[keyspr]L%d:", __LINE__),printf(fmt) |
| #define wrnP(fmt...) printf("Wrn[keyspr]L%d:", __LINE__),printf(fmt) |
| #define MsgP(fmt...) printf("Msg[keyspr]L%d:", __LINE__),printf(fmt) |
| |
| #define KEY_MAP_MAGIC 0xeeffaa00 |
| |
| enum { |
| KEY_FMT__MAC = 0XBB, //string format like 00:01:02:03:04:05 |
| KEY_FMT__ONLEYONE , //only one format means read the total license file as key value |
| KEY_FMT__HDCP , |
| KEY_FMT__HDCP2 , |
| }; |
| |
| //Different keyNames can have the same key format |
| typedef int (*pFunc_getKeyValByLic)(const char* licensePath, u8* keyVal, unsigned* keyValLen, const char* keyName); |
| typedef int (*pFunc_updateLic)(const char* keyName, const char* licensePath);//update the licnese file when burn succeed |
| |
| typedef struct _keyFmtMapping{ |
| unsigned magic; |
| const char* const keyName; |
| const char* const licenseFile; |
| const unsigned keyFmt; |
| pFunc_getKeyValByLic get_key_val; |
| pFunc_updateLic update_license; |
| }KeyFmtMap_t; |
| |
| static int get_key_val_for_fmt_mac(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName); |
| static int get_key_val_for_fmt_hdcp(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName); |
| static int get_key_val_for_fmt_hdcp2rx(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName); |
| static int get_key_val_for_fmt_onlyone(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName); |
| |
| static int update_lic_for_fmt_mac(const char* keyName, const char* licenseName); |
| static int update_lic_for_fmt_hdcp(const char* keyName, const char* licenseName); |
| static int update_lic_for_fmt_hdcp2rx(const char* keyName, const char* licenseName); |
| |
| static const KeyFmtMap_t _keysFmtMapping[] = { |
| /* magic, keyname license file name keyFmt*/ |
| [0] = {KEY_MAP_MAGIC, "mac", "license/mac_ether.ini" , KEY_FMT__MAC , get_key_val_for_fmt_mac , update_lic_for_fmt_mac }, |
| [1] = {KEY_MAP_MAGIC, "mac_bt", "license/mac_bt.ini" , KEY_FMT__MAC , get_key_val_for_fmt_mac , update_lic_for_fmt_mac }, |
| [2] = {KEY_MAP_MAGIC, "mac_wifi", "license/mac_wifi.ini" , KEY_FMT__MAC , get_key_val_for_fmt_mac , update_lic_for_fmt_mac }, |
| [3] = {KEY_MAP_MAGIC, "hdcp", "license/HDCP_LIENCE" , KEY_FMT__HDCP , get_key_val_for_fmt_hdcp , update_lic_for_fmt_hdcp }, |
| [4] = {KEY_MAP_MAGIC, "hdcp2", "license/HDCP2_LIENCE" , KEY_FMT__HDCP2 , get_key_val_for_fmt_hdcp2rx, update_lic_for_fmt_hdcp2rx}, |
| [5] = {KEY_MAP_MAGIC, "secure_boot_set", "license/SECURE_BOOT_SET", KEY_FMT__ONLEYONE, get_key_val_for_fmt_onlyone, NULL}, |
| }; |
| #define _SupportKeysNum (sizeof(_keysFmtMapping)/sizeof(KeyFmtMap_t)) |
| |
| #if 1 //mac begin |
| static int optimus_sdc_burn_check_mac_ini_set_is_valid(const char* setName) |
| { |
| const char* macSets[] = {"Group1", "Group2", "Group3"}; |
| const int nSet = sizeof(macSets)/sizeof(char*); |
| int index = 0; |
| int rc = 0; |
| |
| for (; index < nSet && !rc; ++index) |
| { |
| rc = !strcmp(setName, macSets[index]); |
| } |
| |
| return rc; |
| } |
| |
| typedef struct { |
| char startMac[17 + 3]; //+2 to align 4 |
| char endMac[17 + 3]; //+2 to align 4 |
| unsigned total; |
| unsigned used; |
| }MacGroup_t; |
| |
| typedef struct { |
| unsigned actualGroup; |
| MacGroup_t groups[3];//max group is 3 |
| }KeyInf_mac_t; |
| |
| typedef struct { |
| const char* start; |
| const char* end; |
| unsigned used; |
| unsigned total;//total = end + 1 - start |
| }MacCfg_t; |
| |
| /*static KeyInf_mac_t _bootPart_keyInf_Mac;//Mac key info stored in boot partition*/ |
| |
| static int optimus_update_mac_str_current_val(char* startVal, unsigned used) |
| { |
| int i = 0; |
| |
| if (17 != strlen(startVal)) { |
| DWN_ERR("start(%s) fmt error.\n", startVal); |
| return __LINE__; |
| } |
| |
| MsgP("start[%s], used=%d\n", startVal, used); |
| for (i = 5; i >= 0 && used; --i, (used >>= 8)) |
| { |
| char* grp2 = startVal + i * 3; |
| unsigned grp2Val = simple_strtoul(grp2, NULL, 16); |
| |
| DWN_DBG("gpp2(%s)grep2=%d, used=%d\n", grp2, grp2Val, used); |
| grp2Val += used & 0xff; |
| if (grp2Val > 0xff) |
| { |
| used += 0x100; |
| grp2Val &= 0xff; |
| } |
| sprintf(grp2, "%02x", grp2Val); |
| DWN_DBG("grp[%d]%s\n", i, grp2); |
| } |
| DWN_MSG("Update mac [%s]\n", startVal); |
| |
| return 0; |
| } |
| |
| static int _optimus_get_mac_diff(MacCfg_t* macCfg) |
| { |
| const char* start = macCfg->start; |
| const char* end = macCfg->end; |
| __u64 startVal = 0; |
| __u64 endVal = 0; |
| int i = 0; |
| |
| for (i = 0; i < 6; ++i, start += 3, end += 3) |
| { |
| startVal += simple_strtoul(start, NULL, 16); |
| endVal += simple_strtoul(end, NULL, 16); |
| |
| startVal <<= 8; |
| endVal <<= 8; |
| } |
| startVal >>= 8; |
| endVal >>= 8; |
| DWN_MSG("mac range[%04x%08x, %04x%08x]\n", |
| (unsigned)(startVal>>32), (unsigned)(startVal), |
| (unsigned)(endVal>>32), (unsigned)endVal ); |
| macCfg->total = (unsigned)(endVal + 1 - startVal); |
| return 0; |
| } |
| |
| //update the mac value extracted from mac.ini |
| //To simplest the case, currently one group is supported |
| static int optimus_sdc_burn_parse_mac_ini_key_value(const char* setName, const char* keyName, const char* usrKeyVal) |
| { |
| int rc = 0; |
| int grpN = 0; |
| MacCfg_t* currentMacCfg = (MacCfg_t*)_KEYS_PRV_ITEM_INF_ADDR_MISC; |
| char* keyBuf = (char*)_KEY_VAL_TMP_BUF; |
| KeyInf_mac_t* pKeyInf4Consist = (KeyInf_mac_t*)_KEYS_PRV_ITEM_INF_ADDR_4_CONSIST; |
| |
| rc = strncmp("Group", setName, 5) || ( 6 != strlen(setName) ); |
| if (rc) {//mac.ini only care Groupn |
| return 0; |
| } |
| grpN = setName[5] - '1'; //'1' not '0' |
| if (grpN > 3) { |
| DWN_ERR("Can only support grp1 ~ grp3 now!, grp[%s] not ok\n", setName); |
| return __LINE__; |
| } |
| pKeyInf4Consist->actualGroup = grpN + 1; |
| MacGroup_t* pKeyConsist = pKeyInf4Consist->groups + grpN; |
| |
| _KEYS_PRV_DBG("grp[%d]key=[%s], val=[%s]\n", grpN, keyName, usrKeyVal); |
| //the mac cfg must be in the order: start + end (+used) |
| if (!strcmp("start", keyName)) |
| { |
| currentMacCfg->start = usrKeyVal;//value in memory |
| _currentKey.keySize = strlen(usrKeyVal); |
| strcpy(keyBuf, currentMacCfg->start); |
| keyBuf[_currentKey.keySize] = 0; |
| _currentKey.keyBuf = keyBuf; |
| DWN_DBG("keybuf[%s]\n", keyBuf); |
| memcpy(pKeyConsist->startMac, usrKeyVal, strlen(usrKeyVal)); |
| } |
| else if (!strcmp("end", keyName)) |
| { |
| currentMacCfg->end = usrKeyVal; |
| _currentKey.keySize = strlen(usrKeyVal); |
| _optimus_get_mac_diff(currentMacCfg); |
| memcpy(pKeyConsist->endMac, usrKeyVal, strlen(usrKeyVal)); |
| pKeyConsist->total = currentMacCfg->total; |
| } |
| else if(!strcmp("used", keyName)) |
| { |
| currentMacCfg->used = simple_strtoul(usrKeyVal, NULL, 0); |
| if (currentMacCfg->used >= currentMacCfg->total) { |
| DWN_ERR("mac used(%d) >= total(%d)\n", currentMacCfg->used , currentMacCfg->total); |
| return __LINE__; |
| } |
| pKeyConsist->used = currentMacCfg->used; |
| } |
| |
| if (17 != _currentKey.keySize) { |
| errorP("key size %d of mac(%s) is error, must be 17\n", _currentKey.keySize, usrKeyVal); |
| return __LINE__; |
| } |
| |
| return 0; |
| } |
| |
| static int _update_mac_with_cfg_and_bootpart(KeyInf_mac_t* pKeyInf4Consist, KeyInf_mac_t* pKeyInfInBootPart, |
| u8* keyVal, unsigned* keyValLen) |
| { |
| const int grpNum = pKeyInf4Consist->actualGroup; |
| MacGroup_t* theMacGrpCfg = NULL; |
| MacGroup_t* theMacGrpInBootPart = NULL; |
| unsigned currentUsed = 0; |
| int i = 0; |
| |
| theMacGrpCfg = pKeyInf4Consist->groups; |
| currentUsed = theMacGrpCfg->used; |
| for (; i < grpNum; ++i, ++theMacGrpCfg) |
| { |
| const unsigned leftInCfg = theMacGrpCfg->total - theMacGrpCfg->used; |
| unsigned leftCnt = leftInCfg; |
| if (pKeyInfInBootPart) |
| { |
| theMacGrpInBootPart = pKeyInfInBootPart->groups + i; |
| const unsigned leftInBoot = theMacGrpInBootPart->total - theMacGrpInBootPart->used; |
| DWN_MSG("leftInCfg=%u, leftInBoot=%u, used=%u\n", leftCnt, leftInBoot, theMacGrpInBootPart->used); |
| if (leftCnt < leftInBoot) { |
| DWN_ERR("Excp:leftInCfg[%u] < leftInBoot[%u]\n", leftCnt, leftInBoot); |
| return __LINE__; |
| } |
| if (theMacGrpInBootPart->total != theMacGrpCfg->total) { |
| DWN_ERR("Excp:cfg total[%u] != boot total[%u]\n", |
| theMacGrpCfg->total, theMacGrpInBootPart->total); |
| return __LINE__; |
| } |
| currentUsed = ++theMacGrpInBootPart->used;//used is saved by prev burned |
| } |
| if (currentUsed < theMacGrpCfg->total) {//Find it |
| DWN_MSG("Found available at grp[%d], total=%u, used=%u\n", |
| i, theMacGrpCfg->total, currentUsed); |
| break; |
| } |
| } |
| |
| if (i == grpNum) { |
| DWN_ERR("Can't find available grp,i=%d\n", i); |
| return __LINE__; |
| } |
| |
| *keyValLen = strlen(theMacGrpCfg->startMac); |
| memcpy(keyVal, theMacGrpCfg->startMac, *keyValLen); |
| i = optimus_update_mac_str_current_val((char*)keyVal, currentUsed); |
| return i; |
| } |
| |
| //step 1: parsing license/mac.ini to get 'start' and 'used' |
| //step 2: search the key info in the boot key, if not existed , then append the keyinfo and update total count |
| //step 3: check the 'start' and 'used' is same as which in the boot partition if existed |
| //step 3: get the count recorded in the uboot partition |
| static int get_key_val_for_fmt_mac(const char* licPath, u8* keyVal, unsigned* keyValLen, const char* keyName) |
| { |
| const int MaxLines = 256;// |
| char* lines[MaxLines]; |
| int rc = __LINE__; |
| int validLineNum = 0; |
| KeyInf_mac_t* pKeyInfInBootPart = NULL; |
| KeyInf_mac_t* pKeyInf4Consist = (KeyInf_mac_t*)_KEYS_PRV_ITEM_INF_ADDR_4_CONSIST; |
| |
| memset(pKeyInf4Consist, 0, sizeof(KeyInf_mac_t)); |
| validLineNum = parse_ini_file_2_valid_lines(licPath, (char*)keyVal, *keyValLen, lines); |
| if (!validLineNum) { |
| DWN_ERR("error in parse ini file\n"); |
| return __LINE__; |
| } |
| |
| rc = optimus_ini_trans_lines_2_usr_params((const char* *)lines, validLineNum, |
| optimus_sdc_burn_check_mac_ini_set_is_valid, |
| optimus_sdc_burn_parse_mac_ini_key_value); |
| if (rc) { |
| DWN_ERR("Fail in get cfg from %s\n", licPath); |
| return __LINE__; |
| } |
| *keyValLen = _currentKey.keySize; |
| memcpy(keyVal, _currentKey.keyBuf, _currentKey.keySize); |
| keyVal[_currentKey.keySize] = 0; |
| |
| #if 1 |
| rc = optimus_sdc_bootPart_lic_get_key_infdata(keyName, (void**)&pKeyInfInBootPart); |
| if (rc) { |
| DWN_ERR("Fail in get key inf from boot part\n"); |
| return __LINE__; |
| } |
| #endif |
| rc = _update_mac_with_cfg_and_bootpart(pKeyInf4Consist, pKeyInfInBootPart, keyVal, keyValLen); |
| |
| return rc; |
| } |
| |
| static int update_lic_for_fmt_mac(const char* keyName, const char* licenseName) |
| { |
| int rc = 0; |
| |
| rc = optimus_sdc_bootPart_lic_update_key_inf(keyName, (u8*)_KEYS_PRV_ITEM_INF_ADDR_4_CONSIST, sizeof(KeyInf_mac_t)); |
| |
| return rc; |
| } |
| #endif//MAC |
| |
| |
| static int get_key_val_for_fmt_hdcp(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName) |
| { |
| int rc = __LINE__; |
| |
| |
| return rc; |
| } |
| |
| static int get_key_val_for_fmt_hdcp2rx(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName) |
| { |
| int rc = __LINE__; |
| |
| |
| return rc; |
| } |
| |
| static int get_key_val_for_fmt_onlyone(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName) |
| { |
| int rc = 0; |
| char _cmd[96]; |
| |
| optimus_sdc_burn_switch_to_extmmc(); |
| |
| sprintf(_cmd, "fatload mmc 0:1 0x%p %s", keyVal, licenseName); |
| rc = run_command(_cmd, 0); |
| if (rc) { |
| errorP("failed in cmd[%s]\n", _cmd); |
| return __LINE__; |
| } |
| |
| *keyValLen = simple_strtoul(getenv("filesize"), NULL, 16); |
| |
| return rc; |
| } |
| |
| static int update_lic_for_fmt_hdcp(const char* keyName, const char* licenseName) |
| { |
| int rc = 0; |
| |
| |
| return rc; |
| } |
| |
| static int update_lic_for_fmt_hdcp2rx(const char* keyName, const char* licenseName) |
| { |
| int rc = 0; |
| |
| |
| return rc; |
| } |
| |
| int optimus_sdc_keysprovider_init(void) |
| { |
| /*return optimus_sdc_bootPart_lic_download();*/ |
| return 0; |
| } |
| |
| int optimus_sdc_keysprovider_exit(void) |
| { |
| /*return optimus_sdc_bootPart_lic_upload();*/ |
| return 0; |
| } |
| |
| //check whether the key license is existed and supported |
| //keyName is getted from keys.conf in package like PC burning tool |
| int optimus_sdc_keysprovider_open(const char* keyName, const void** pHdle) |
| { |
| int i = 0; |
| int rc = __LINE__; |
| |
| const KeyFmtMap_t* pMappedKey = &_keysFmtMapping[0]; |
| for (i=0; i < _SupportKeysNum; ++i, ++pMappedKey) { |
| rc = strcmp(keyName, pMappedKey->keyName); |
| if (rc) continue;//keyName not mapped |
| *pHdle = pMappedKey; |
| return 0; |
| } |
| |
| return rc; |
| } |
| |
| int optimus_sdc_keysprovider_get_keyval(const void* pHdle, u8* pBuf, unsigned* keySz) |
| { |
| const KeyFmtMap_t* pMappedKey = (const KeyFmtMap_t*)pHdle; |
| const char* const keyName = pMappedKey->keyName; |
| const char* licPath = pMappedKey->licenseFile; |
| int rc = 0; |
| |
| if (KEY_MAP_MAGIC != pMappedKey->magic) { |
| errorP("magic should be %x, but %x\n", KEY_MAP_MAGIC, pMappedKey->magic); |
| return __LINE__; |
| } |
| rc = pMappedKey->get_key_val(licPath, pBuf, keySz, keyName); |
| if (rc) { |
| errorP("Fail in getKeyVal for key[%s] at lic path[%s]\n", keyName, licPath); |
| return __LINE__; |
| } |
| |
| return rc; |
| } |
| |
| int optimus_sdc_keysprovider_update_license(const void* pHdle) |
| { |
| const KeyFmtMap_t* pMappedKey = (const KeyFmtMap_t*)pHdle; |
| const char* const keyName = pMappedKey->keyName; |
| const char* licPath = pMappedKey->licenseFile; |
| int rc = 0; |
| |
| if (KEY_MAP_MAGIC != pMappedKey->magic) { |
| errorP("magic should be %x, but %x\n", KEY_MAP_MAGIC, pMappedKey->magic); |
| return __LINE__; |
| } |
| if (!pMappedKey->update_license) return 0; |
| |
| rc = pMappedKey->update_license(keyName, licPath); |
| if (rc) { |
| errorP("Fail in getKeyVal for key[%s] at lic path[%s]\n", keyName, licPath); |
| return __LINE__; |
| } |
| |
| return 0; |
| } |
| |