diff options
author | Srikantha Meesala <srikantha@in.ibm.com> | 2019-01-24 02:23:02 -0600 |
---|---|---|
committer | RAJA DAS <rajadas2@in.ibm.com> | 2019-03-14 04:07:39 -0500 |
commit | e02d72ae04fe9f0c763a18e10c09aad692510c2c (patch) | |
tree | d74bbe12791cd6ad026d580b11ed007940b389d4 /src | |
parent | 8a2bb59e3dc98a2342a118ab0052f5ae88624fc5 (diff) | |
download | talos-sbe-e02d72ae04fe9f0c763a18e10c09aad692510c2c.tar.gz talos-sbe-e02d72ae04fe9f0c763a18e10c09aad692510c2c.zip |
White/Black/Grey List Binary dump full SBE implementation
Change-Id: I7e547677102edb93b562dae767fd5a01b86958ce
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/70842
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: RAJA DAS <rajadas2@in.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/build/security/securityRegListGen.py | 48 | ||||
-rw-r--r-- | src/sbefw/app/common/sbecmdgeneric.C | 28 | ||||
-rw-r--r-- | src/sbefw/app/common/sbecmdgeneric.H | 1 | ||||
-rw-r--r-- | src/sbefw/core/corefiles.mk | 3 | ||||
-rw-r--r-- | src/sbefw/core/sbeSecurity.C | 304 | ||||
-rw-r--r-- | src/sbefw/core/sbeSecurity.H | 68 | ||||
-rw-r--r-- | src/sbefw/core/securityAlgo.C | 253 | ||||
-rw-r--r-- | src/sbefw/core/securityAlgo.H | 307 |
8 files changed, 802 insertions, 210 deletions
diff --git a/src/build/security/securityRegListGen.py b/src/build/security/securityRegListGen.py index e25c8e74..4703c9be 100644 --- a/src/build/security/securityRegListGen.py +++ b/src/build/security/securityRegListGen.py @@ -5,7 +5,7 @@ # # OpenPOWER sbe Project # -# Contributors Listed Below - COPYRIGHT 2017,2018 +# Contributors Listed Below - COPYRIGHT 2017,2019 # [+] International Business Machines Corp. # # @@ -58,6 +58,7 @@ arguments:\n\ -o, --output output directory\n\ -w, --whitelist print whitelist read from csv\n\ -b, --blacklist print blacklist read from csv\n\ +-g, --greylist print greylist read from csv\n\ -i, --info get version info of the security list\n\ -d, --debug enable debug traces\n\ -v, --verbose enable verbose traces" @@ -92,6 +93,7 @@ def gen_file(whitelist_tables, blacklist_tables, greyList): header = ("#ifndef __SBE_SECURITY_GEN_H\n"+ "#define __SBE_SECURITY_GEN_H\n\n"+ "#include \"sbeSecurity.H\"\n\n"+ + "#include \"securityAlgo.H\"\n\n"+ "using namespace SBE_SECURITY;\n\n") tables = (('WHITELIST', 'whitelist', whitelist_tables), @@ -122,7 +124,7 @@ namespace """+namespace+""" 1 byte for running count - we are good with uint8_t till the total paths are less than 256 */ - map_t< range_t<"""+table1_range_type+""">, """+table1_index_type+""" > _t1[] = { + _t1_t _t1[] = { // length of the table = """+s_list_len(table[0])+""" """+s_table1_gen(tablename, table[0])+""" }; @@ -141,7 +143,7 @@ namespace """+namespace+""" We are good with uint16_t, till the number of paths to table 3 from each key is less than 65536 */ - map_t< """+table2_value_type+""", """+table2_index_type+""" > _t2[] = { + _t2_t _t2[] = { // length of the table = """+s_list_len(table[1])+""" """+s_table2_gen(tablename, table[1])+""" }; @@ -149,30 +151,26 @@ namespace """+namespace+""" table 3 values = 2 byte value bit 16-31 of the 32-bit address */ - """+table3_value_type+""" _t3[] = { + _t3_t _t3[] = { // length of the table = """+s_list_len(table[2])+""" """+s_table3_gen(tablename, table[2])+""" }; - table< map_t< range_t<"""+table1_range_type+""">, """+table1_index_type+""" > > t1 = - {sizeof(_t1)/sizeof(map_t< range_t<"""+table1_range_type+""">, """+table1_index_type+""" >), + _t1_table_t t1 = + {sizeof(_t1)/sizeof(_t1_t), 0xFF000000, _t1}; - table< map_t< """+table2_value_type+""", """+table2_index_type+""" > > t2 = - {sizeof(_t2)/sizeof(map_t< """+table2_value_type+""", """+table2_index_type+""" >), + _t2_table_t t2 = + {sizeof(_t2)/sizeof(_t2_t), 0x00FF0000, _t2}; - table<"""+table3_value_type+"""> t3 = - {sizeof(_t3)/sizeof("""+table3_value_type+"""), + _t3_table_t t3 = + {sizeof(_t3)/sizeof(_t3_t), 0x0000FFFF, _t3}; bool isPresent(uint32_t i_addr) { - return SBE_SECURITY::_is_present - < """+table1_range_type+""", """+table1_index_type+""", - """+table2_value_type+""", """+table2_index_type+""", - """+table3_value_type+"""> - (t1, t2, t3, i_addr); + return _is_present(t1, t2, t3, i_addr); } }""") @@ -186,20 +184,18 @@ namespace GREYLIST Address = 4 byte Mask = 8 byte */ - map_t< """+greylist_addr_type+""", """+greylist_mask_type+""" > _t1[] = { + _gl_t1_t _t1[] = { """+s_greylist_table_gen(greyList)+""" }; - table< map_t< """+greylist_addr_type+""", """+greylist_mask_type+""" > > t1 = - {sizeof(_t1)/sizeof(map_t< """+greylist_addr_type+""", """+greylist_mask_type+""" >), + _gl_t1_table_t t1 = + {sizeof(_t1)/sizeof(_gl_t1_t), 0xFFFFFFFF, _t1}; bool isPresent(uint32_t i_addr, uint64_t i_mask) { - return SBE_SECURITY::_is_present - < """+greylist_addr_type+""", """+greylist_mask_type+"""> - (t1, i_addr, i_mask); + return _is_present(t1, i_addr, i_mask); } }""") footer = "\n#endif //__SBE_SECURITY_GEN_H" @@ -486,7 +482,7 @@ def s_table1_gen(id, table): # write table 1 string str_table1 = "" for i,(key, value) in enumerate(table): - str_table1 += '{{0x%02x, 0x%02x}, 0x%02x}, ' % (((key & 0xFF00) >> 8), + str_table1 += '{0x%02x, 0x%02x, 0x%02x}, ' % (((key & 0xFF00) >> 8), (key & 0x00FF), value) if(0 == ((i+1) % 4)): @@ -540,8 +536,8 @@ def main(argv): try: opts, args = getopt.getopt(sys.argv[1:], - "f:o:wbidvhW:B:", - ['file=', 'output=', 'whitelist', 'blacklist', 'info', 'debug', 'verbose', 'help', 'wt=', 'bt=']) + "f:o:wbgidvhW:B:", + ['file=', 'output=', 'whitelist', 'blacklist', 'greylist', 'info', 'debug', 'verbose', 'help', 'wt=', 'bt=']) except getopt.GetoptError as err: exit(INVALID_USAGE, str(err)) @@ -565,6 +561,8 @@ def main(argv): print_info = "whitelist" elif opt in ('-b', '--blacklist'): print_info = "blacklist" + elif opt in ('-g', '--greylist'): + print_info = "greylist" elif opt in ('-f', '--file'): assert os.path.exists(arg), "file doesn't exist at:"+str(arg) SECURITY_LIST = str(arg) @@ -666,6 +664,8 @@ def main(argv): exit(PRINT_AND_EXIT, s_list_hex("whitelist:", whitelist, 8)) if(print_info == 'blacklist'): exit(PRINT_AND_EXIT, s_list_hex("blacklist:", blacklist, 8)) + if(print_info == 'greylist'): + exit(PRINT_AND_EXIT, greylist) if(VERBOSE): print s_list_hex("whitelist:", whitelist, 8) diff --git a/src/sbefw/app/common/sbecmdgeneric.C b/src/sbefw/app/common/sbecmdgeneric.C index 708249c4..91f89b0a 100644 --- a/src/sbefw/app/common/sbecmdgeneric.C +++ b/src/sbefw/app/common/sbecmdgeneric.C @@ -43,6 +43,7 @@ #include "sbeglobals.H" #include "sbeXipUtils.H" #include "sbeMemAccessInterface.H" +#include "sbeSecurity.H" #include "fapi2.H" //#include "p9_xip_image.h" @@ -441,21 +442,32 @@ uint32_t sbeSecurityListBinDump( uint8_t *i_pArg ) rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1, (sizeof(dumpAddr)/sizeof(uint64_t)), &dumpAddr, true); - if(SBE_SEC_OPERATION_SUCCESSFUL != rc) { SBE_ERROR(SBE_FUNC" Failed to extract SBE_HOST_PSU_MBOX_REG1"); break; } - SBE_INFO(SBE_FUNC "Security Dump Addr [0x%08X][%08X]", - SBE::higher32BWord(dumpAddr), - SBE::lower32BWord(dumpAddr)); - - //////////////////////////////////////////////////////// - // Do your processing here with dumpAddr - //////////////////////////////////////////////////////// + SBE::higher32BWord(dumpAddr), + SBE::lower32BWord(dumpAddr)); + /// Initialise the PBA with the above address from stash, + /// The access API would use it in auto-increment mode. + p9_PBA_oper_flag pbaFlag; + pbaFlag.setOperationType(p9_PBA_oper_flag::INJ); + sbeMemAccessInterface PBAInterface( + SBE_MEM_ACCESS_PBA, + dumpAddr, + &pbaFlag, + SBE_MEM_ACCESS_WRITE, + sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES); + /// Send TOC of table header count and list of _T1, _T2 and _T3 data + fapiRc = SBE_SECURITY::sendSecurityListDumpToHB(&PBAInterface); + if(fapiRc != fapi2::FAPI2_RC_SUCCESS) + { + SBE_ERROR(SBE_FUNC"Failed to send security table data to hostboot"); + break; + } }while(0); // Send the response diff --git a/src/sbefw/app/common/sbecmdgeneric.H b/src/sbefw/app/common/sbecmdgeneric.H index cdbcf108..4fcf3c08 100644 --- a/src/sbefw/app/common/sbecmdgeneric.H +++ b/src/sbefw/app/common/sbecmdgeneric.H @@ -32,6 +32,7 @@ #include <stdint.h> #include <p9_sbe_hb_structures.H> +#include "sbeMemAccessInterface.H" typedef struct sbeStashMemoryPair { diff --git a/src/sbefw/core/corefiles.mk b/src/sbefw/core/corefiles.mk index 2b110523..b14d0b0f 100644 --- a/src/sbefw/core/corefiles.mk +++ b/src/sbefw/core/corefiles.mk @@ -5,7 +5,7 @@ # # OpenPOWER sbe Project # -# Contributors Listed Below - COPYRIGHT 2015,2018 +# Contributors Listed Below - COPYRIGHT 2015,2019 # [+] International Business Machines Corp. # # @@ -42,6 +42,7 @@ COREPIBMEM-CPP-SOURCES += sbeglobals.C COREPIBMEM-CPP-SOURCES += sbeMemAccessInterface.C COREPIBMEM-CPP-SOURCES += sbeSecureMemRegionManager.C COREPIBMEM-CPP-SOURCES += sbeSecurity.C +COREPIBMEM-CPP-SOURCES += securityAlgo.C COREPIBMEM-CPP-SOURCES += chipop_handler.C COREPIBMEM-CPP-SOURCES += ipl.C ifeq ($(SBE_S0_SUPPORT), 1) diff --git a/src/sbefw/core/sbeSecurity.C b/src/sbefw/core/sbeSecurity.C index bf5bc103..3ff902bb 100644 --- a/src/sbefw/core/sbeSecurity.C +++ b/src/sbefw/core/sbeSecurity.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER sbe Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2017,2018 */ +/* Contributors Listed Below - COPYRIGHT 2017,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -25,164 +25,214 @@ #include "sbeSecurity.H" #include "sbetrace.H" #include "sbeglobals.H" +#include "fapi2.H" #include "sbeSecurityGen.H" namespace SBE_SECURITY { - -// Figure out at compile time, the number of shifts required for the mask -constexpr uint32_t get_shift_len(uint32_t mask, uint8_t shifts = 0) +//---------------------------------------------------------------------------- +bool isAllowed(const uint32_t i_addr, uint64_t i_mask, accessType i_type) +{ + bool ret = true; + if(SBE_GLOBAL->sbeFWSecurityEnabled) + { + if(i_type == WRITE) + { + ret = WHITELIST::isPresent(i_addr); + if( (ret == false ) && (i_mask != 0xffffffffffffffffull )) + { + ret = GREYLIST::isPresent(i_addr, i_mask); + } + } + else if(i_type == READ) + ret = !BLACKLIST::isPresent(i_addr); + SBE_INFO("SBE_SECURITY access[%d] allowed[%d] addr[0x%08x]", + i_type, ret, i_addr); + } + return ret; +} +//---------------------------------------------------------------------------- +uint32_t updateAndSendSecTOCHdr( sbeMemAccessInterface *i_pMemInterface ) { - return ((mask>>shifts) & 0x01) ? (shifts) : (get_shift_len(mask, ++shifts)); + #define SBE_FUNC "updateAndSendSecTOCHdr" + SBE_ENTER(SBE_FUNC); + uint32_t fapiRc = fapi2::FAPI2_RC_SUCCESS; + + sec_header_dump_t l_secListDumpHdr; + /// Send the list of _T1, _T2 and _T3 header count + l_secListDumpHdr.wl_t1_count = WHITELIST::t1.size; + l_secListDumpHdr.wl_t2_count = WHITELIST::t2.size; + l_secListDumpHdr.wl_t3_count = WHITELIST::t3.size; + + l_secListDumpHdr.bl_t1_count = BLACKLIST::t1.size; + l_secListDumpHdr.bl_t2_count = BLACKLIST::t2.size; + l_secListDumpHdr.bl_t3_count = BLACKLIST::t3.size; + + l_secListDumpHdr.gl_t1_count = GREYLIST::t1.size; + + SBE_INFO("SBE_SECURITY whitelist t1[%d] t2[%d] t3[0x%d] ", + WHITELIST::t1.size, WHITELIST::t2.size, WHITELIST::t3.size); + SBE_INFO("SBE_SECURITY blacklist t1[%d] t2[%d] t3[0x%d] ", + BLACKLIST::t1.size, BLACKLIST::t2.size, BLACKLIST::t3.size); + SBE_INFO("SBE_SECURITY greylist t1[%d] ", GREYLIST::t1.size); + + fapiRc = i_pMemInterface->accessWithBuffer(&l_secListDumpHdr, + sizeof(l_secListDumpHdr), + false); + if(fapiRc != fapi2::FAPI2_RC_SUCCESS) + { + SBE_ERROR(SBE_FUNC "Failed to write accessWithBuffer to hostboot"); + } + + SBE_EXIT(SBE_FUNC); + return fapiRc; + #undef SBE_FUNC } -template <typename Func> -map_t<bool, int32_t> binary_search( - const uint32_t search_key, - range_t<int32_t> x_range, - Func get_element) +//---------------------------------------------------------------------------- +uint32_t sbeSecurityWhiteBlackListDump( sbeMemAccessInterface *i_pMemInterface, + const secListType &i_listType ) { - map_t<bool, int32_t> ret = {false, 0}; // found=false + #define SBE_FUNC "sbeSecurityWhiteBlackListDump" + SBE_ENTER(SBE_FUNC); + uint32_t fapiRc = fapi2::FAPI2_RC_SUCCESS; + _t1_t * t1 = NULL; + uint32_t t1_size = 0; + _t2_t * t2 = NULL; + uint32_t t2_size = 0; + _t3_t * t3 = NULL; + uint32_t t3_size = 0; + if( i_listType == SEC_WHITE_LIST ) + { + t1 = WHITELIST::_t1; + t1_size = WHITELIST::t1.size; + + t2 = WHITELIST::_t2; + t2_size = WHITELIST::t2.size; + + t3 = WHITELIST::_t3; + t3_size = WHITELIST::t3.size; + } + else if( i_listType == SEC_BLACK_LIST ) + { + t1 = BLACKLIST::_t1; + t1_size = BLACKLIST::t1.size; + + t2 = BLACKLIST::_t2; + t2_size = BLACKLIST::t2.size; - while((x_range.start <= x_range.end) && - (ret.key == false)) + t3 = BLACKLIST::_t3; + t3_size = BLACKLIST::t3.size; + } + do { - int32_t midpoint = (x_range.start + x_range.end) / 2; - SBE_DEBUG("binary_search : midpoint[0x%08x]", - midpoint); - uint32_t ele = get_element(midpoint); - SBE_DEBUG("binary_search : search_key[0x%08x] ele[0x%08x]", - search_key, - ele); - if(search_key == ele) + // Update and Send the whitelist T1 + for( uint32_t i = 0; i < t1_size; i++) { - ret.key = true; - ret.value = midpoint; + fapiRc = i_pMemInterface->accessWithBuffer(&t1[i].key_start, + sizeof(uint8_t), false); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) break; + fapiRc = i_pMemInterface->accessWithBuffer(&t1[i].key_end, + sizeof(uint8_t), false); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) break; + fapiRc = i_pMemInterface->accessWithBuffer(&t1[i].value, + sizeof(uint8_t), false); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) break; } - else if(search_key < ele) + + // Update and Send the whitelist T2 + for( uint32_t i = 0; i < t2_size; i++) { - x_range.end = midpoint - 1; + fapiRc = i_pMemInterface->accessWithBuffer(&t2[i].key, + sizeof(uint8_t), false); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) break; + fapiRc = i_pMemInterface->accessWithBuffer(&t2[i].value, + sizeof(uint16_t), false); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) break; } - else + + // Update and Send the whitelist T3 + for( uint32_t i = 0; i < t3_size; i++) { - x_range.start = midpoint + 1; + fapiRc = i_pMemInterface->accessWithBuffer(&t3[i].value, + sizeof(uint16_t), false); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) break; } - SBE_DEBUG("binary_search : x_range.start[0x%08x] x_range.end[0x%08x]", - x_range.start, - x_range.end); } - SBE_DEBUG("binary_search : ret[%d]",ret.key); - return ret; + while(0); + if(fapiRc != fapi2::FAPI2_RC_SUCCESS) + { + SBE_ERROR(SBE_FUNC "Failed to send Black/WhiteListDump to hostboot"); + } + SBE_EXIT(SBE_FUNC); + return fapiRc; + #undef SBE_FUNC } -template <typename M1_T, typename M1_U, - typename M2_T, typename M2_U, - typename T3> -bool _is_present(const table< map_t< range_t<M1_T>, M1_U > > &table1, - const table< map_t<M2_T, M2_U> > &table2, - const table< T3 > &table3, - const uint32_t i_addr) +//---------------------------------------------------------------------------- +uint32_t sbeSecurityGreyListDump( sbeMemAccessInterface *i_pMemInterface ) { -#define SBE_FUNC "SBE_SECURITY::_is_present" + #define SBE_FUNC "sbeSecurityGreyListDump" SBE_ENTER(SBE_FUNC); - for(size_t i = 0; i < table1.size; i++) + uint32_t fapiRc = fapi2::FAPI2_RC_SUCCESS; + + // Update and Send the blacklist T1 + for(uint32_t i = 0; i < GREYLIST::t1.size; i++) { - uint32_t search_key = (i_addr & table1.mask) >> get_shift_len(table1.mask); - if((table1.table[i].key.start <= search_key) && - (table1.table[i].key.end >= search_key)) - { - SBE_DEBUG(SBE_FUNC" table1:found key[0x%x] table index[%d]", - search_key, i); - // Found the range where key might belong to - search_key = (i_addr & table2.mask) >> get_shift_len(table2.mask); - range_t<int32_t> search_range = {}; - search_range.start = i ? table1.table[i-1].value : 0; - search_range.end = table1.table[i].value - 1; - map_t<bool, int32_t> search_result = - binary_search( - search_key, - search_range, - [&table2](int32_t midpoint) -> uint32_t { - return table2.table[midpoint].key; - }); - if(search_result.key == true) - { - SBE_DEBUG(SBE_FUNC" table2:found key[0x%x] table index[%d]", - search_key, - search_result.value); - // Found the key - search_range.start = (search_result.value ? - table2.table[search_result.value-1].value : 0); - search_range.end = - table2.table[search_result.value].value - 1; - search_key = (i_addr & table3.mask) >> - get_shift_len(table3.mask); - search_result = binary_search( - search_key, - search_range, - [&table3](int32_t midpoint) -> uint32_t { - return table3.table[midpoint]; - }); - if(search_result.key == true) - { - SBE_DEBUG(SBE_FUNC" table3:found key[0x%x] table index[%d]", - search_key, - search_result.value); - // Found the number - return true; - } - } - } + fapiRc = i_pMemInterface->accessWithBuffer(&GREYLIST::_t1[i].key, + sizeof(uint32_t), false); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) break; + fapiRc = i_pMemInterface->accessWithBuffer(&GREYLIST::_t1[i].value, + sizeof(uint64_t), false); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) break; } - SBE_EXIT(SBE_FUNC); - return false; -#undef SBE_FUNC -} -template <typename T1, typename T2 > -bool _is_present(const table< map_t< T1, T2 > > &table1, - const T1 i_addr, - const T2 i_mask) -{ -#define SBE_FUNC "SBE_SECURITY::_is_present " - SBE_ENTER(SBE_FUNC"Searching address/mask table"); - bool ret = false; - for(size_t i = 0; i < table1.size; i++) + if(fapiRc != fapi2::FAPI2_RC_SUCCESS) { - // Not using mask in table for search - if((table1.table[i].key == i_addr) && - (( i_mask & (~table1.table[i].value)) == 0 )) - { - SBE_DEBUG(SBE_FUNC" table1:found addr[0x%x] table index[%d]", - i_addr, i); - ret = true; - break; - } + SBE_ERROR(SBE_FUNC "Failed to send GreyListDump to hostboot"); } SBE_EXIT(SBE_FUNC); - return ret; -#undef SBE_FUNC + return fapiRc; + #undef SBE_FUNC } -bool isAllowed(const uint32_t i_addr, uint64_t i_mask, accessType i_type) +//---------------------------------------------------------------------------- +uint32_t sendSecurityListDumpToHB(sbeMemAccessInterface *i_pMemInterface) { - bool ret = true; - if(SBE_GLOBAL->sbeFWSecurityEnabled) + #define SBE_FUNC "sendSecurityListDumpToHB" + SBE_ENTER(SBE_FUNC); + uint32_t fapiRc = fapi2::FAPI2_RC_SUCCESS; + do { - if(i_type == WRITE) - { - ret = WHITELIST::isPresent(i_addr); - if( (ret == false ) && (i_mask != 0xffffffffffffffffull )) - { - ret = GREYLIST::isPresent(i_addr, i_mask); - } - } - else if(i_type == READ) - ret = !BLACKLIST::isPresent(i_addr); - SBE_INFO("SBE_SECURITY access[%d] allowed[%d] addr[0x%08x]", - i_type, ret, i_addr); + // Update and Send the list of TOC of _T1, _T2 and _T3 header count + fapiRc = updateAndSendSecTOCHdr(i_pMemInterface); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) break; + + // Update and Send the whitelist T1,T2 and T3 data + fapiRc = sbeSecurityWhiteBlackListDump(i_pMemInterface, SEC_WHITE_LIST); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) break; + + // Update and Send the blacklist T1,T2 and T3 data + fapiRc = sbeSecurityWhiteBlackListDump(i_pMemInterface,SEC_BLACK_LIST); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) break; + + // Update and Send the greylist T1 data + fapiRc = sbeSecurityGreyListDump(i_pMemInterface); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) break; + uint8_t l_endOfdump = 0; + fapiRc = i_pMemInterface->accessWithBuffer(&l_endOfdump, + sizeof(l_endOfdump), + true); + if(fapiRc != fapi2::FAPI2_RC_SUCCESS) break; } - return ret; + while(0); + if(fapiRc != fapi2::FAPI2_RC_SUCCESS) + { + SBE_ERROR(SBE_FUNC "Failed to write SecData Dump to hostboot"); + } + SBE_EXIT(SBE_FUNC); + return fapiRc; + #undef SBE_FUNC } } // namespace SBE_SECURITY diff --git a/src/sbefw/core/sbeSecurity.H b/src/sbefw/core/sbeSecurity.H index d30daf6f..1b9c0a0a 100644 --- a/src/sbefw/core/sbeSecurity.H +++ b/src/sbefw/core/sbeSecurity.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER sbe Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2017,2018 */ +/* Contributors Listed Below - COPYRIGHT 2017,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -26,38 +26,28 @@ #define __SBE_SECURITY_H #include <stdint.h> +#include <securityAlgo.H> +#include "sbeMemAccessInterface.H" namespace SBE_SECURITY { + typedef enum { READ = 0, WRITE } accessType; - // type to define a range - template <typename T> - struct range_t - { - T start; - T end; - }; - - // key-value map used for the tables - template <typename T, typename U> - struct map_t - { - T key; - U value; - }; - - // table data structure - template <typename T> - struct table + /** + * @brief An enumeration of all Security list types + */ + enum secListType { - uint32_t size; - uint32_t mask; - T *table; + SEC_WHITE_LIST = 0x0, + SEC_BLACK_LIST = 0x1, + SEC_GREY_LIST = 0x2, + // Don't count this in the list type, just to intialize the list type + SEC_INVALID_LIST = 0xF, }; /* @brief isAllowed - Public function used for address verification @@ -73,35 +63,13 @@ namespace SBE_SECURITY bool isAllowed(const uint32_t i_addr, const uint64_t i_mask, accessType i_type); - /* @brief _is_present - Look up tables to find if the given - * address is present - * @param[in] table1 - table 1 - map with a range and running count - * @param[in] table2 - table 2 - map with value and running count - * @param[in] table3 - table 3 - array with values - * @param[in] i_addr - given address to look up + /* @brief sendSecurityListDumpToHB - Public function used for sending + * security dump to hostboot * - * @return - boolean to denote if the address in present - * in the list of tables - */ - template <typename M1_T, typename M1_U, - typename M2_T, typename M2_U, - typename T3> - bool _is_present(const table< map_t< range_t<M1_T>, M1_U > > &table1, - const table< map_t<M2_T, M2_U> > &table2, - const table< T3 > &table3, - const uint32_t i_addr); - - /* @brief _is_present - Look up tables to find if the given - * address with mask is present - * @param[in] table1 - table 1 - map with a range and running count - * @param[in] i_addr - given address to look up - * @param[in] mask - mask to look up + * @param[in] i_pMemInterface - pointer to memory interface object * - * @return - boolean to denote if the address in present + * @return - SBE secondary RC */ - template <typename T1, typename T2 > - bool _is_present(const table< map_t< T1, T2 > > &table1, - const T1 i_addr, - const T2 i_mask); + uint32_t sendSecurityListDumpToHB(sbeMemAccessInterface *i_pMemInterface); } #endif //__SBE_SECURITY_H diff --git a/src/sbefw/core/securityAlgo.C b/src/sbefw/core/securityAlgo.C new file mode 100644 index 00000000..1cdc8198 --- /dev/null +++ b/src/sbefw/core/securityAlgo.C @@ -0,0 +1,253 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/core/securityAlgo.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2019 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include "securityAlgo.H" +#include <stddef.h> +#ifndef __PPE__ + #include <string.h> +static bool isSecurityListInitDone = false; +#endif + +// Helper function to figure out the number of shifts required for the mask +constexpr uint32_t get_shift_len(uint32_t mask, uint8_t shifts = 0) +{ + return ((mask>>shifts) & 0x01) ? (shifts) : (get_shift_len(mask, ++shifts)); +} + +template <typename Func> +map_t binary_search( + const uint32_t search_key, + range_t x_range, + Func get_element) +{ + map_t ret = {false, 0}; // found=false + + while((x_range.start <= x_range.end) && + (ret.key == false)) + { + int32_t midpoint = (x_range.start + x_range.end) / 2; + uint32_t ele = get_element(midpoint); + if(search_key == ele) + { + ret.key = true; + ret.value = midpoint; + } + else if(search_key < ele) + { + x_range.end = midpoint - 1; + } + else + { + x_range.start = midpoint + 1; + } + } + return ret; +} + +//---------------------------------------------------------------------------- +// @brief Public function used for init all white, black and grey list table +// data, WhiteList/ BalckList Tables [T1, T2 and T3] and GreyList [T1] +//---------------------------------------------------------------------------- +bool _is_present( const _t1_table_t &table1, + const _t2_table_t &table2, + const _t3_table_t &table3, + const uint32_t i_addr) +{ + for(size_t i = 0; i < table1.size; i++) + { + uint32_t search_key = (i_addr & table1.mask) >> get_shift_len(table1.mask); + if((table1.table[i].key_start <= search_key) && + (table1.table[i].key_end >= search_key)) + { + search_key = (i_addr & table2.mask) >> get_shift_len(table2.mask); + range_t search_range = {}; + search_range.start = i ? table1.table[i-1].value : 0; + search_range.end = table1.table[i].value - 1; + map_t search_result = + binary_search( + search_key, + search_range, + [&table2](int32_t midpoint) -> uint32_t { + return table2.table[midpoint].key; + }); + if(search_result.key == true) + { + // Found the key + search_range.start = (search_result.value ? + table2.table[search_result.value-1].value : 0); + search_range.end = + table2.table[search_result.value].value - 1; + search_key = (i_addr & table3.mask) >> + get_shift_len(table3.mask); + search_result = binary_search( + search_key, + search_range, + [&table3](int32_t midpoint) -> uint32_t { + return table3.table[midpoint].value; + }); + if(search_result.key == true) + { + // Found the number + return true; + } + } + } + } + return false; +} + +//---------------------------------------------------------------------------- +// @brief Look up tables to find if the given address with mask is present +// on GreyList Table [T1] +//---------------------------------------------------------------------------- +bool _is_present(const _gl_t1_table_t &table1, + const uint32_t i_addr, + const uint64_t i_mask) +{ + bool ret = false; + for(size_t i = 0; i < table1.size; i++) + { + // Not using mask in table for search + if((table1.table[i].key == i_addr) && + (( i_mask & (~table1.table[i].value)) == 0 )) + { + ret = true; + break; + } + } + return ret; +} + +//---------------------------------------------------------------------------- +// @brief Public function used for address verification for a given type of +// access. +//---------------------------------------------------------------------------- +bool isAccessAllowed(const uint32_t i_addr, uint64_t i_mask, + secAccessType i_type) +{ + bool ret = true; +#ifndef __PPE__ + if(!isSecurityListInitDone) + { + ret = false; // Table Init was not yet done + } + else if(i_type == WRITE_ACCESS) + { + ret = _is_present( secListTableSupport.wl_t1, + secListTableSupport.wl_t2, + secListTableSupport.wl_t3, + i_addr ); + if( (ret == false ) && (i_mask != 0xffffffffffffffffull )) + { + ret = _is_present( secListTableSupport.gl_t1, + i_addr, i_mask ); + } + } + else if(i_type == READ_ACCESS) + { + ret = !_is_present( secListTableSupport.bl_t1, + secListTableSupport.bl_t2, + secListTableSupport.bl_t3, + i_addr ); + } +#endif + return ret; +} + +//---------------------------------------------------------------------------- +// @brief Public function used for init all white, black and grey list table +// data, WhiteList/ BalckList Tables [T1, T2 and T3] and GreyList [T1] +//---------------------------------------------------------------------------- +bool securityAccessTablesInit(const void * i_buf ) +{ + bool ret = false; +#ifndef __PPE__ + do + { + uint8_t * l_buf = reinterpret_cast<uint8_t*>(const_cast<void*>(i_buf)); + if(isSecurityListInitDone) + { + break; // Table Init was already done + } + // Read header + sec_header_dump_t* l_table_sizes = + reinterpret_cast<sec_header_dump_t*>(l_buf); + // Read and Update whitelist tables1 + size_t l_size = SEC_LIST_TABLE_HDR_SIZE; + secListTableSupport.wl_t1.size = l_table_sizes->wl_t1_count; + secListTableSupport.wl_t1.mask = WHITELIST_TABLE1_MASK; + + secListTableSupport.wl_t1.table = (_t1_t*) malloc((sizeof(_t1_t))*(l_table_sizes->wl_t1_count)); + memcpy( secListTableSupport.wl_t1.table, l_buf+SEC_LIST_TABLE_HDR_SIZE, (sizeof(_t1_t))*((l_table_sizes->wl_t1_count)) ); + + // Read and Update whitelist tables2 + l_size += (sizeof (_t1_t))*(l_table_sizes->wl_t1_count) ; + secListTableSupport.wl_t2.size = l_table_sizes->wl_t2_count; + secListTableSupport.wl_t2.mask = WHITELIST_TABLE2_MASK; + secListTableSupport.wl_t2.table = (_t2_t*)malloc((sizeof(_t2_t))*(l_table_sizes->wl_t2_count)); + memcpy( secListTableSupport.wl_t2.table, l_buf+l_size, (sizeof(_t2_t))*(l_table_sizes->wl_t2_count) ); + + // Read and Update whitelist tables3 + l_size += (sizeof (_t2_t))*(l_table_sizes->wl_t2_count) ; + secListTableSupport.wl_t3.size = l_table_sizes->wl_t3_count; + secListTableSupport.wl_t3.mask = WHITELIST_TABLE3_MASK; + secListTableSupport.wl_t3.table = (_t3_t*)malloc((sizeof(_t3_t))*(l_table_sizes->wl_t3_count)); + memcpy( secListTableSupport.wl_t3.table, l_buf+l_size, (sizeof(_t3_t))*(l_table_sizes->wl_t3_count) ); + + // Read and Update blacklist tables1 + l_size += (sizeof (_t3_t))*(l_table_sizes->wl_t3_count) ; + secListTableSupport.bl_t1.size = l_table_sizes->bl_t1_count; + secListTableSupport.bl_t1.mask = BLACKLIST_TABLE1_MASK; + secListTableSupport.bl_t1.table = (_t1_t*)malloc((sizeof(_t1_t))*(l_table_sizes->bl_t1_count)); + memcpy( secListTableSupport.bl_t1.table, l_buf+l_size,(sizeof(_t1_t))*(l_table_sizes->bl_t1_count) ); + + // Read and Update blacklist tables2 + l_size += (sizeof (_t1_t))*(l_table_sizes->bl_t1_count) ; + secListTableSupport.bl_t2.size = l_table_sizes->bl_t2_count; + secListTableSupport.bl_t2.mask = BLACKLIST_TABLE2_MASK; + secListTableSupport.bl_t2.table = (_t2_t*)malloc((sizeof(_t2_t))*(l_table_sizes->bl_t2_count)); + memcpy( secListTableSupport.bl_t2.table, l_buf+l_size,(sizeof(_t2_t))*(l_table_sizes->bl_t2_count) ); + + // Read and Update blacklist tables3 + l_size += (sizeof (_t2_t))*(l_table_sizes->bl_t2_count) ; + secListTableSupport.bl_t3.size = l_table_sizes->bl_t3_count; + secListTableSupport.bl_t3.mask = BLACKLIST_TABLE3_MASK; + secListTableSupport.bl_t3.table = (_t3_t*)malloc((sizeof(_t3_t))*(l_table_sizes->bl_t3_count)); + memcpy( secListTableSupport.bl_t3.table, l_buf+l_size,(sizeof(_t3_t))*(l_table_sizes->bl_t3_count) ); + + // Read and Update greylist tables1 + l_size += (sizeof (_t3_t))*(l_table_sizes->bl_t3_count) ; + secListTableSupport.gl_t1.size = l_table_sizes->gl_t1_count; + secListTableSupport.gl_t1.mask = GREYLIST_TABLE1_MASK; + secListTableSupport.gl_t1.table = (_gl_t1_t*)malloc((sizeof(_gl_t1_t))*(l_table_sizes->gl_t1_count)); + memcpy( secListTableSupport.gl_t1.table, l_buf+l_size,(sizeof(_gl_t1_t))*(l_table_sizes->gl_t1_count)); + + isSecurityListInitDone = true; + ret = true; + } + while(0); +#endif + return ret; +} diff --git a/src/sbefw/core/securityAlgo.H b/src/sbefw/core/securityAlgo.H new file mode 100644 index 00000000..43e96447 --- /dev/null +++ b/src/sbefw/core/securityAlgo.H @@ -0,0 +1,307 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/core/securityAlgo.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2019 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __SECURITY_ALGO_H +#define __SECURITY_ALGO_H + +#include <stdint.h> +#include <stddef.h> + +/* + Whitelist , Blacklist and Greylist are part of the Security validation + of any register. Each list has been sub divided into 3 tables [t1, t2 and + t3] as mentioned bellow. Table data will be used on security algorithm to + validates register address is part of Whitelist, Blacklist and Greylist + or not. + + # -----------------------------------------------------------------# + # Step 1: [register list] # + # || # + # \/ # + # {base_address1 : [chiplet range1, chiplet range2]} # + #..................................................................# + # Eg: [01ABCDEF, 02ABCDEF, 04ABCDEF, 05ABCDEF, 10UVWXYZ, 11UVWXYZ] # + # || # + # \/ # + # {ABCDEF : [0102, 0405], UVWXYZ : [1011]} # + # -----------------------------------------------------------------# + # Step 2: {base_address1 : [chiplet range1, chiplet range2]} # + # || # + # \/ # + # {chiplet range1 : [base_address1, base_address2]} # + #..................................................................# + # Eg: {ABCDEF : [0102, 0405], UVWXYZ : [0405, 1020]} # + # || # + # \/ # + # {0102 : [ABCDEF], 0405 : [ABCDEF, UVWXYZ], 1020 : [UVWXYZ]} # + # -----------------------------------------------------------------# + # Step 3: {chiplet range1 : [base_address1, base_address2]} # + # || # + # \/ # + # {chiplet range1 : {key1 : [base_addr1, base_Addr2]}} # + #..................................................................# + # Eg: {0102 : [ABCDEF], 0405 : [ABCDEF, UVWXYZ], 1020 : [UVWXYZ]} # + # || # + # \/ # + # {0102 : {AB : [CDEF]}, # + # 0405 : {AB : [CDEF], UV : [WXYZ]}, # + # 1020 : {UV : [WXYZ]}} # + # -----------------------------------------------------------------# + # Step 4: {chiplet range1 : {key1 : [base_addr1, base_Addr2]}} # + # || # + # \/ # + # table1, table2, table3 # + #..................................................................# + # Eg: {0102 : {AB : [CD, EF]}, # + # 0405 : {AB : [CD, EF], UV : [WX, YZ]}, # + # 1020 : {UV : [WX, YZ]}} # + # || # + # \/ # + # table1: {0102 : 1, 0405 : 3, 1020 : 4} # + # table2: {AB : 2, AB : 4, UV : 6, UV : 8} # + # table3: {CD, EF, CD, EF, WX, YZ, WX, YZ} # + # -----------------------------------------------------------------# + + + table 1: + keys = 2byte - (start , end) of + the ranges in bit 0-7 of the 32-bit address + values = running count of the paths to table2 + + for example - if ranges are 0x20-0x37, 0x01-0x01, 0x10-0x17 and has + 1, 2 and 3 paths respectively to table 2 + then table 1 will have {0x20,0x37} = 01, {0x01,0x01} = 3, {0x10,0x17} = 7 + + 1 byte for running count - we are good with uint8_t till the + total paths are less than 256 + + table 2 + keys = unique 1 byte numbers having same prefix for each + range in table 1 key - bit 8-15 from a 32-bit address + values = running count of paths from each of the keys + + for example - if element a has 1 path, b has 0 and c has 3 paths + then table 1 will have a = 1, b = 1, c = 4 + + 1 byte for key + 1 byte for number of paths + We are good with uint8_t, + till the number of paths to table 3 from each key is less than 256 + + table 3 + values = 2 byte value bit 16-31 of the 32-bit address + + */ + +#define WHITELIST_TABLE1_MASK 0xFF000000 +#define WHITELIST_TABLE2_MASK 0x00FF0000 +#define WHITELIST_TABLE3_MASK 0x0000FFFF +#define BLACKLIST_TABLE1_MASK 0xFF000000 +#define BLACKLIST_TABLE2_MASK 0x00FF0000 +#define BLACKLIST_TABLE3_MASK 0x0000FFFF +#define GREYLIST_TABLE1_MASK 0xFFFFFFFF + +#ifndef __PPE__ + #pragma pack(1) +#endif + // struct range_t and map_t are supporting data types in SecurityAlgo + // type to define a range + struct range_t + { + int32_t start; + int32_t end; + }; + // key-value map used for the tables + struct map_t + { + bool key; + int32_t value; + }; + + /*@brief Format of T1 table date */ + typedef struct + { + uint8_t key_start; + uint8_t key_end; + uint8_t value; + } _t1_t; // Total 3 bytes + + /*@brief Format of T2 table date */ + typedef struct + { + uint8_t key; + uint16_t value; + } _t2_t; // Total 3 bytes + + /*@brief Format of T3 table date */ + typedef struct + { + uint16_t value; + } _t3_t; // Total 2 bytes + + + /*@brief Format of Grey list table date */ + typedef struct + { + uint32_t key; + uint64_t value; + } _gl_t1_t; // Total 12 bytes + + + // table data structure + /* @brief Format of White / Black list table-1 */ + typedef struct + { + uint32_t size; + uint32_t mask; + _t1_t *table; + } _t1_table_t; + + /* @brief Format of White / Black list table-2 */ + typedef struct + { + uint32_t size; + uint32_t mask; + _t2_t *table; + } _t2_table_t; + + /* @brief Format of White / Black list table-3 */ + typedef struct + { + uint32_t size; + uint32_t mask; + _t3_t *table; + } _t3_table_t; + + /* @brief Format of Grey list table-1 */ + typedef struct + { + uint32_t size; + uint32_t mask; + _gl_t1_t *table; + } _gl_t1_table_t; + + /* @brief Format of SecurityList dump header */ + typedef struct + { + uint16_t wl_t1_count; + uint16_t wl_t2_count; + uint16_t wl_t3_count; + uint16_t bl_t1_count; + uint16_t bl_t2_count; + uint16_t bl_t3_count; + uint16_t gl_t1_count; + } sec_header_dump_t; + + // Security Access Types + typedef enum + { + READ_ACCESS = 0, + WRITE_ACCESS + } secAccessType; + + typedef struct GenSecurityListTables + { + GenSecurityListTables(){} + _t1_table_t wl_t1; + _t2_table_t wl_t2; + _t3_table_t wl_t3; + + _t1_table_t bl_t1; + _t2_table_t bl_t2; + _t3_table_t bl_t3; + + _gl_t1_table_t gl_t1; + } GenSecurityListTables_t; +#ifndef __PPE__ + #pragma pack() +#endif + + static struct GenSecurityListTables secListTableSupport; + // size of GenericFspMboxMessage_t header size + constexpr size_t SEC_LIST_TABLE_HDR_SIZE = sizeof(sec_header_dump_t); + + /* @brief isAllowed - Public function used for address verification + * for a given type of access + * + * @param[in] i_addr - given address to verify + * @param[in] i_mask - mask for data + * @param[in] i_type - access type - READ/WRITE + * + * @return - boolean to denote if the access on the address + * is allowed or not + * + bool _isAllowed(const uint32_t i_addr, const uint64_t i_mask, + accessType i_type); + + * @brief _is_present - Look up tables to find if the given + * address ii present + * @param[in] table1 - table 1 - map with a range and running count + * @param[in] table2 - table 2 - map with value and running count + * @param[in] table3 - table 3 - array with values + * @param[in] i_addr - given address to look up + * + * @return - boolean to denote if the address in present + * in the list of tables + */ + + bool _is_present( const _t1_table_t &table1, + const _t2_table_t &table2, + const _t3_table_t &table3, + const uint32_t i_addr); + + /* @brief _is_present - Look up tables to find if the given + * address with mask is present + * @param[in] table1 - table 1 - map with a range and running count + * @param[in] i_addr - given address to look up + * @param[in] mask - mask to look up + * + * @return - boolean to denote if the address in present + */ + bool _is_present(const _gl_t1_table_t &table1, + const uint32_t i_addr, + const uint64_t i_mask); + + /* @brief securityAccessTablesInit - Public function used for + * init all white, black and grey list table data + * @param[in] i_i_buf - tables data + * + * @return - boolean to denote if the access on the table + * data is allowed or not + */ + bool securityAccessTablesInit(const void * i_buf ); + + /* @brief isAccessAllowed - Public function used for address verification + * for a given type of access + * + * @param[in] i_addr - given address to verify + * @param[in] i_mask - mask for data + * @param[in] i_type - access type - READ_ACCESS / WRITE_ACCESS + * + * @return - boolean to denote if the access on the address + * is allowed or not + */ + bool isAccessAllowed(const uint32_t i_addr, const uint64_t i_mask, + secAccessType i_type); +#endif //__SECURITY_ALGO_H |