def test_sb_write_all_available_region(self, bl, memType): sb_commandDictionay['writeMemory'].cumulativeWrite = False startAddress, endAddress, length = common_util.get_available_memory_region( bl, memType) sb_commandDictionay['writeMemory'].length = length sb_commandDictionay[ 'writeMemory'].data = common_util.generate_random_data_file( bl, startAddress, length) sb_commandDictionay['writeMemory'].dataType = 'file_bin' sb_commandDictionay['writeMemory'].startAddress = startAddress sb_commandDictionay['writeMemory'].endAddress = startAddress + length sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'writeMemory') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success # Read back the data from memory readFile = os.path.join(bl.vectorsDir, 'read_data_from_memory.bin') status, results = bl.read_memory(startAddress, length, readFile) assert status == bootloader.status.kStatus_Success # The two data files should be the same. with open(sb_commandDictionay['writeMemory'].data, 'rb') as fileObj1: data1 = fileObj1.read() fileObj1.close() with open(readFile, 'rb') as fileObj2: data2 = fileObj2.read() fileObj2.close() assert data1 == data2
def test_sb_fill_all_available_memory(self, bl, memType, pattern_format): sb_commandDictionay['fillMemory'].cumulativeFill = False startAddress, endAddress, length = common_util.get_available_memory_region( bl, memType) # --------------------------------------------------------------------------------- if pattern_format == 'byte': pattern = kFilledValue & 0xFF elif pattern_format == 'short': pattern = kFilledValue & 0xFFFF elif pattern_format == 'word': pattern = kFilledValue & 0xFFFFFFFF # --------------------------------------------------------------------------------- sb_commandDictionay['fillMemory'].pattern = pattern sb_commandDictionay['fillMemory'].patternFormat = pattern_format sb_commandDictionay['fillMemory'].startAddress = startAddress sb_commandDictionay['fillMemory'].endAddress = startAddress + length sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'fillMemory') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success # Read back the filling data and compare with the filling data. read_file = os.path.join(bl.vectorsDir, 'read_data_from_memory.bin') status, results = bl.read_memory(startAddress, length, read_file) assert common_util.is_fill_memory_correct(read_file, length, pattern, pattern_format) == True
def test_sb_write_unaligned_address(self, bl, memType): sb_commandDictionay['writeMemory'].cumulativeWrite = False startAddress, endAddress, length = common_util.get_available_memory_region( bl, memType) # Here we just need a small amount data for this case. Set the length as 1KB. length = 0x400 alignedBase = bl.target.programAlignmentSize for offset in range(1, alignedBase): sb_commandDictionay['writeMemory'].length = length sb_commandDictionay['writeMemory'].dataType = 'file_bin' sb_commandDictionay[ 'writeMemory'].startAddress = startAddress + offset sb_commandDictionay[ 'writeMemory'].endAddress = startAddress + length + offset sb_commandDictionay[ 'writeMemory'].data = common_util.generate_random_data_file( bl, sb_commandDictionay['writeMemory'].startAddress, length) sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'writeMemory') status, results = bl.receive_sb_file(sbFilePath) if memType == 'flash': assert status == bootloader.status.kStatus_FlashAlignmentError elif memType == 'ram': assert status == bootloader.status.kStatus_Success
def test_encrypt_noncontiguous_sections_within_512bytes(self, bl): # Get the path of the QCB bin file path qcbBinFile = os.path.abspath( os.path.join(bl.vectorsDir, 'QSPI', kQspiConfigBlockFile)) # Use two keyblob regions to encrypt two non-contiguous setion data # The first keyblob region sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_START_ADDR = 0x68002300 # keyblob start address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_END_ADDR = 0x680023FF # keyblob end address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].OTFAD_CTX0_CTR = "FFFFFFFFFFFFFFFF" # Section data 0 needs to be encrypted sbCmdDict['otfadDecryption'].encrypted_type_0 = 'encrypt_write' sbCmdDict[ 'otfadDecryption'].encrypted_data_0 = qcbBinFile # Here can be any other bin files # Only encrypt 16 bytes data encrypted_data_size_0 = 16 sbCmdDict['otfadDecryption'].data_location_start_0 = sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_START_ADDR sbCmdDict['otfadDecryption'].data_location_end_0 = sbCmdDict[ 'otfadDecryption'].data_location_start_0 + encrypted_data_size_0 # The second keyblob region sbCmdDict[ 'otfadDecryption'].OTFAD_CTX1_START_ADDR = 0x68002400 # keyblob start address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX1_END_ADDR = 0x680027FF # keyblob end address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX1_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].OTFAD_CTX1_CTR = "FFFFFFFFFFFFFFFF" # Section data 1 needs to be encrypted sbCmdDict['otfadDecryption'].encrypted_type_1 = 'encrypt_write' sbCmdDict[ 'otfadDecryption'].encrypted_data_1 = qcbBinFile # Here can be any other bin files # Only encrypt 16 bytes data encrypted_data_size_1 = 16 sbCmdDict['otfadDecryption'].data_location_start_1 = sbCmdDict[ 'otfadDecryption'].OTFAD_CTX1_START_ADDR sbCmdDict['otfadDecryption'].data_location_end_1 = sbCmdDict[ 'otfadDecryption'].data_location_start_1 + encrypted_data_size_1 # Enable the qspi in bd file sbCmdDict['enableQspi'].qspiConfigBlock = qcbBinFile sbCmdDict['enableQspi'].qcbLocation = 0x20000000 # Erase qspi flash in bd file sbCmdDict['flashEraseRegion'].startAddress = 0x68000000 sbCmdDict['flashEraseRegion'].endAddress = 0x68004000 # Generate sb file according to the parameters sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'enableQspi', 'flashEraseRegion', 'otfadDecryption') status, results = bl.receive_sb_file(sbFilePath) # Obviously, the qspi flash 0x68002400 ~ 0x68002500 is cumulative programmed. So send this sb file to target will get QSPI Flash Command Failure assert status == bootloader.status.kStatus_Success
def test_sb_jump_to_sp_pc_with_arg(self, bl, hasArg): # Extract SP and PC address from app demo bin file, and then jump to SP and PC without argument (elfFile, hexFile, binFile) = common_util.get_led_demo_path(bl) sb_commandDictionay['writeMemory'].cumulativeWrite = False sb_commandDictionay['writeMemory'].data = binFile sb_commandDictionay['writeMemory'].dataType = 'app_bin' sb_commandDictionay[ 'writeMemory'].startAddress = bl.target.BL_APP_VECTOR_TABLE_ADDRESS sb_commandDictionay['writeMemory'].endAddress = sb_commandDictionay[ 'writeMemory'].startAddress + os.path.getsize(binFile) sb_commandDictionay['jumpStackPoint'].hasArg = hasArg if hasArg: # Set the argument as random 32-bit data if has. sb_commandDictionay['jumpStackPoint'].arg = random.randint( 0, 0xffffffff) else: sb_commandDictionay['jumpStackPoint'].arg = None # Generate sb file sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'writeMemory', 'jumpStackPoint') # After excuting receive-sb-file the led will blink immediately and blhost returns kStatus_AbortDataPhase. status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_AbortDataPhase # Send command to blhost, it will fail status, results = bl.get_property( bootloader.properties.kPropertyTag_CurrentVersion) status != bootloader.status.kStatus_Success # Let led blink for some time so that we can see the correct phenomenon. time.sleep(3)
def test_sb_jump_to_pc_address(self, bl): # Extract PC address from app demo bin file, and then jump to PC. # The case can pass on K80 while fail on L5K. Jump will not support jump to explicit address, but only support jump to app entry point (elfFile, hexFile, binFile) = common_util.get_led_demo_path(bl) sb_commandDictionay['writeMemory'].cumulativeWrite = False sb_commandDictionay['writeMemory'].data = binFile sb_commandDictionay['writeMemory'].dataType = 'app_bin' sb_commandDictionay[ 'writeMemory'].startAddress = bl.target.BL_APP_VECTOR_TABLE_ADDRESS sb_commandDictionay['writeMemory'].endAddress = sb_commandDictionay[ 'writeMemory'].startAddress + os.path.getsize(binFile) # Generate sb file sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'writeMemory', 'jumpEntryPoint') # After excuting receive-sb-file the led will blink immediately and blhost returns kStatus_AbortDataPhase. status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_AbortDataPhase # Send command to blhost, it will fail status, results = bl.get_property( bootloader.properties.kPropertyTag_CurrentVersion) status != bootloader.status.kStatus_Success # Let led blink for some time so that we can see the correct phenomenon. time.sleep(3)
def test_encrypt_data_with_its_start_address_not_match_keyblob_start_address( self, bl): # Get the path of the QCB bin file path qcbBinFile = os.path.abspath( os.path.join(bl.vectorsDir, 'QSPI', kQspiConfigBlockFile)) # Only use one keyblob region sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_START_ADDR = 0x68001000 # keyblob start address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_END_ADDR = 0x6800FFFF # keyblob end address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].OTFAD_CTX0_CTR = "FFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].encrypted_type_0 = 'encrypt_write' # Encrypt the qspi config block data. Here can be any bin files sbCmdDict['otfadDecryption'].encrypted_data_0 = qcbBinFile # Get the encrypted data size data_size = os.path.getsize( sbCmdDict['otfadDecryption'].encrypted_data_0) # The start address does not match the keyblob start address sbCmdDict['otfadDecryption'].data_location_start_0 = sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_START_ADDR + 0x1000 sbCmdDict['otfadDecryption'].data_location_end_0 = sbCmdDict[ 'otfadDecryption'].data_location_start_0 + data_size # Enable the qspi in bd file sbCmdDict['enableQspi'].qspiConfigBlock = qcbBinFile sbCmdDict['enableQspi'].qcbLocation = 0x20000000 # Erase qspi flash in bd file sbCmdDict['flashEraseRegion'].startAddress = 0x68000000 sbCmdDict['flashEraseRegion'].endAddress = 0x68006000 # Generate sb file according to the parameters sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'enableQspi', 'flashEraseRegion', 'otfadDecryption') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success plaintext = qcbBinFile # Read back the ciphertext ciphertext = os.path.join(bl.vectorsDir, 'read_data_from_memory.bin') status, results = bl.read_memory( sbCmdDict['otfadDecryption'].data_location_start_0, data_size, ciphertext) assert status == bootloader.status.kStatus_Success # The plaintext should not be the same with the ciphertext with open(plaintext, 'rb') as plain_Obj: plain_data = plain_Obj.read() plain_Obj.close() with open(ciphertext, 'rb') as cipher_Obj: ciphter_data = cipher_Obj.read() cipher_Obj.close() assert plain_data != ciphter_data
def test_erase_all_QSPI_with_sb_file(self, bl): # Get qspi block data sbCmdDict['enableQspi'].qspiConfigBlock = os.path.abspath( os.path.join(bl.vectorsDir, 'QSPI', kQspiConfigBlockFile)) # Get the location of the qspi block data sbCmdDict['enableQspi'].qcbLocation = 0x20000000 # Generate sb file sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'enableQspi', 'qspiFlashEraseAll') print sbFilePath status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success
def test_sb_load_nothing_to_nonzero_size_space(self, bl): # data size is zero while start address is not equal to end address (return kStatusRomLdrChecksum) sb_commandDictionay['writeMemory'].cumulativeWrite = False sb_commandDictionay['writeMemory'].length = 0 sb_commandDictionay['writeMemory'].dataType = 'file_bin' sb_commandDictionay['writeMemory'].startAddress = 0x1000 sb_commandDictionay['writeMemory'].endAddress = 0x2000 sb_commandDictionay[ 'writeMemory'].data = common_util.generate_random_data_file( bl, sb_commandDictionay['writeMemory'].startAddress, sb_commandDictionay['writeMemory'].length) sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'writeMemory') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatusRomLdrIdNotFound
def test_sb_erase_out_of_range(self, bl, memType): startAddress, endAddress, length = common_util.get_available_memory_region( bl, memType) # Here we just need a small amount data for this case. Set the erase length as 1 sector. length = common_util.get_flash_sector_size(bl) # Make sure the start_addr is anligned and near the end of the memory region. sb_commandDictionay[ 'flashEraseRegion'].startAddress = endAddress + 1 - bl.target.eraseAlignmentSize sb_commandDictionay[ 'flashEraseRegion'].endAddress = sb_commandDictionay[ 'flashEraseRegion'].startAddress + length sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'flashEraseRegion') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatusMemoryRangeInvalid
def test_sb_erase_available_flash_region(self, bl, availableFlashSize): startAddress, endAddress, length = common_util.get_available_memory_region( bl, 'flash') # 1. Get actual erased length according to the parameter if availableFlashSize == 'zero': length = 0 elif availableFlashSize == 'oneSectorSize': length = common_util.get_flash_sector_size(bl) elif availableFlashSize == 'allAvailableSize': length = length # 2. erase with blhost command status, results = bl.flash_erase_region(startAddress, length) assert status == bootloader.status.kStatus_Success # 3. write random data to [startAddress, endAddress] randomFile = common_util.generate_random_data_file( bl, startAddress, length) status, results = bl.write_memory(startAddress, randomFile) assert status == bootloader.status.kStatus_Success # 4. generate sb file and erase with sb command sb_commandDictionay['flashEraseRegion'].startAddress = startAddress sb_commandDictionay[ 'flashEraseRegion'].endAddress = startAddress + length sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'flashEraseRegion') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success # 5. read data from [startAddress, endAddress] filePath = os.path.join(bl.vectorsDir, 'read_data_from_memory.bin') status, results == bl.read_memory(startAddress, length, filePath) assert status == bootloader.status.kStatus_Success # 6. verify all the data are FF flag = True fileObj = open(filePath, 'rb') for i in range(0, length): fileObj.seek(i) data_tmp = fileObj.read(1) if ord(data_tmp) != 0xFF: flag = False break fileObj.close() assert flag == True if bl.target.bootloaderType == bootsources.kBootROM_ExecuteROM: # 7. unsecure the flash status, results = bl.flash_erase_all_unsecure() assert status == bootloader.status.kStatus_Success else: pass
def test_sb_erase_all_internal_flash(self, bl): # 1. generate sb file with "erase all" and send the sb file to target, should be success sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'internalFlashEraseAll') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success # 2. get flash region that can be erased by 'erase all' with sb file startAddress, endAddress, length = common_util.get_available_memory_region( bl, 'flash') # 3. write random data to [startAddress, endAddress], should be success randomFile = common_util.generate_random_data_file( bl, startAddress, length) status, results = bl.write_memory(startAddress, randomFile) assert status == bootloader.status.kStatus_Success # 4. erase all the internal flash with sb file, should be success status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success # 5. read data from [startAddress, endAddress] filePath = os.path.join(bl.vectorsDir, 'read_data_from_memory.bin') status, results == bl.read_memory(startAddress, length, filePath) assert status == bootloader.status.kStatus_Success # 6. verify all the data are FF flag = True fileObj = open(filePath, 'rb') for i in range(0, length): fileObj.seek(i) data_tmp = fileObj.read(1) if ord(data_tmp) != 0xFF: flag = False break fileObj.close() assert flag == True if bl.target.bootloaderType == bootsources.kBootROM_ExecuteROM: # 7. reset the target, flash should be in secure state status, results = bl.reset() assert status == bootloader.status.kStatus_Success time.sleep(2) status, results = bl.get_property( bootloader.properties.kPropertyTag_FlashSecurityState) assert status == bootloader.status.kStatus_Success assert results[0] == 1 # 8. unsecure the flash status, results = bl.flash_erase_all_unsecure() assert status == bootloader.status.kStatus_Success else: pass
def test_sb_fill_all_reserved_region(self, bl, memType): sb_commandDictionay['fillMemory'].cumulativeFill = False startAddress, endAddress, length = common_util.get_reserved_memory_region( bl, memType) if length == 0: pass # ROM has no reserved flash region else: sb_commandDictionay['fillMemory'].pattern = kFilledValue sb_commandDictionay['fillMemory'].patternFormat = 'word' sb_commandDictionay['fillMemory'].startAddress = startAddress sb_commandDictionay[ 'fillMemory'].endAddress = startAddress + length sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'fillMemory') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatusMemoryRangeInvalid
def test_sb_fill_memory_out_of_range(self, bl, memType): sb_commandDictionay['fillMemory'].cumulativeFill = False sb_commandDictionay['fillMemory'].pattern = kFilledValue sb_commandDictionay['fillMemory'].patternFormat = 'word' startAddress, endAddress, length = common_util.get_available_memory_region( bl, memType) # Here we just need a small amount data for this case. Set the length as 1KB. length = 0x400 # Make sure the start_addr is anligned and near the end of the memory region. sb_commandDictionay[ 'fillMemory'].startAddress = endAddress + 1 - bl.target.programAlignmentSize sb_commandDictionay['fillMemory'].endAddress = sb_commandDictionay[ 'fillMemory'].startAddress + length sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'fillMemory') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatusMemoryRangeInvalid
def test_sb_erase_unaligned_length(self, bl, memType): startAddress, endAddress, length = common_util.get_available_memory_region( bl, memType) # Here we just need a small amount data for this case. Set the length as 1KB. length = 0x400 alignBase = bl.target.eraseAlignmentSize for i in range(1, alignBase): sb_commandDictionay['flashEraseRegion'].startAddress = startAddress sb_commandDictionay[ 'flashEraseRegion'].endAddress = startAddress + length + i sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'flashEraseRegion') status, results = bl.receive_sb_file(sbFilePath) if memType == 'flash': assert status == bootloader.status.kStatus_FlashAlignmentError elif memType == 'ram': # erase ram region (including available region and reserved reigion) should return kStatus_FlashAddressError assert status == bootloader.status.kStatus_FlashAddressError
def test_sb_erase_all_reserved_region(self, bl, memType): startAddress, endAddress, length = common_util.get_reserved_memory_region( bl, memType) sb_commandDictionay['flashEraseRegion'].startAddress = startAddress sb_commandDictionay[ 'flashEraseRegion'].endAddress = startAddress + length sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'flashEraseRegion') status, results = bl.receive_sb_file(sbFilePath) if memType == 'flash': # ROM has no reserved region, erase zero length flash should return kStatus_Success, otherwise kStatusMemoryRangeInvalid if length == 0: assert status == bootloader.status.kStatus_Success else: assert status == bootloader.status.kStatusMemoryRangeInvalid elif memType == 'ram': # erase ram region (including available region and reserved reigion) should return kStatus_FlashAddressError assert status == bootloader.status.kStatus_FlashAddressError
def test_sb_cumulative_fill(self, bl, memType): sb_commandDictionay['fillMemory'].cumulativeFill = True sb_commandDictionay['fillMemory'].pattern = kFilledValue sb_commandDictionay['fillMemory'].patternFormat = 'word' startAddress, endAddress, length = common_util.get_available_memory_region( bl, memType) # Here we just need a small amount data for this case. Set the length as 1KB. length = 0x400 sb_commandDictionay['fillMemory'].startAddress = startAddress sb_commandDictionay['fillMemory'].endAddress = startAddress + length sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'fillMemory') status, results = bl.receive_sb_file(sbFilePath) if memType == 'flash': assert status == bootloader.status.kStatus_FlashCommandFailure or status == bootloader.status.kStatusMemoryCumulativeWrite elif memType == 'ram': assert status == bootloader.status.kStatus_Success
def test_sb_jump_to_entry_point(self, bl): # .out and .elf file has entry point while .bin file doesn't have. (elfFile, hexFile, binFile) = common_util.get_led_demo_path(bl) sb_commandDictionay['writeMemory'].cumulativeWrite = False sb_commandDictionay['writeMemory'].data = elfFile sb_commandDictionay['writeMemory'].dataType = 'app_out' # Generate sb file sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'writeMemory', 'jumpEntryPoint') # After excuting receive-sb-file the led will blink immediately and blhost returns kStatus_AbortDataPhase. status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_AbortDataPhase # Send command to blhost, it will fail status, results = bl.get_property( bootloader.properties.kPropertyTag_CurrentVersion) status != bootloader.status.kStatus_Success # Let led blink for some time so that we can see the correct phenomenon. time.sleep(3)
def test_sb_write_all_reserved_region(self, bl, memType): sb_commandDictionay['writeMemory'].cumulativeWrite = False startAddress, endAddress, length = common_util.get_reserved_memory_region( bl, memType) if length == 0: pass # ROM has no flash reserved region. else: sb_commandDictionay['writeMemory'].length = length sb_commandDictionay[ 'writeMemory'].data = common_util.generate_random_data_file( bl, startAddress, length) sb_commandDictionay['writeMemory'].dataType = 'file_bin' sb_commandDictionay['writeMemory'].startAddress = startAddress sb_commandDictionay[ 'writeMemory'].endAddress = startAddress + length sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'writeMemory') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatusMemoryRangeInvalid
def test_sb_flash_erase_unsecure(self, bl): if bl.target.bootloaderType != bootsources.kBootROM_ExecuteROM: pytest.skip('This case only supports the ROM-resident bootloader.') else: # 1. erase all the flash status, results = bl.flash_erase_all() assert status == bootloader.status.kStatus_Success # 2. generate sb file with "erase unsecure all" and send the sb file to target sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'flashEraseAllUnsecure') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success # 3. reset target status, results = bl.reset() assert status == bootloader.status.kStatus_Success time.sleep(2) # 4. check the flash security state, should be unsecure. status, results = bl.get_property( bootloader.properties.kPropertyTag_FlashSecurityState) assert status == bootloader.status.kStatus_Success assert results[0] == 0
def test_sb_erase_available_ram_region(self, bl, availableRamSize): startAddress, endAddress, length = common_util.get_available_memory_region( bl, 'ram') # 1. Get actual erased length according to the parameter if availableRamSize == 'zero': length = 0 elif availableRamSize == 'oneSectorSize': length = common_util.get_flash_sector_size(bl) elif availableRamSize == 'allAvailableSize': length = length # 2. generate sb file and erase with sb command sb_commandDictionay['flashEraseRegion'].startAddress = startAddress sb_commandDictionay[ 'flashEraseRegion'].endAddress = startAddress + length sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'flashEraseRegion') status, results = bl.receive_sb_file(sbFilePath) if length == 0: assert status == bootloader.status.kStatus_Success else: # erase ram region (including available region and reserved reigion) should return kStatus_FlashAddressError assert status == bootloader.status.kStatus_FlashAddressError
def test_enable_QSPI_with_sb_file(self, bl, qcbLocation): # Operate qspi flash will fail before enable qspi startAddress, actualLength = get_QSPI_flash_address_and_length( 1, 'Sectors', 'StartOfMemory') # Creat random file that contains actualLength bytes. randomFile = common_util.generate_random_data_file( bl, startAddress, actualLength) status, results = bl.write_memory(startAddress, randomFile) assert status == bootloader.status.kStatus_QspiNotConfigured # Get qspi block data sbCmdDict['enableQspi'].qspiConfigBlock = os.path.abspath( os.path.join(bl.vectorsDir, 'QSPI', kQspiConfigBlockFile)) # Get the location of the qspi block data sbCmdDict['enableQspi'].qcbLocation = qcbLocation # Generate sb file sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'internalFlashEraseAll', 'enableQspi') status, results = bl.receive_sb_file(sbFilePath) if qcbLocation == 0: if bl.target.bootloaderType == bootsources.kBootFlash_ExecuteFlash: # The memory address 0x0 is in the reserved region for flash-resident bootloader. assert status == bootloader.status.kStatusMemoryRangeInvalid else: # Cannot enable QSPI at 0x0 even it is available. assert status == bootloader.status.kStatus_InvalidArgument # Operate qspi flash will fail status, results = bl.flash_erase_region(startAddress, actualLength) assert status == bootloader.status.kStatus_QspiNotConfigured else: assert status == bootloader.status.kStatus_Success # Operate qspi flash will be successful after enable qspi status, results = bl.flash_erase_region(startAddress, actualLength) assert status == bootloader.status.kStatus_Success
def test_sb_program_4bytes_ifr(self, bl): if not bl.target.hasErasableIFR: pytest.skip('\nThis chip has no erasable IFR.\n') else: # Progam the erasable IFR from index 0x30 ~ 0x33 sb_commandDictionay['programIfr'].ifrIndex1 = 0x30 sb_commandDictionay['programIfr'].ifrValue1 = 0xFFFFFFFF sb_commandDictionay['programIfr'].ifrIndex2 = 0x31 sb_commandDictionay['programIfr'].ifrValue2 = 0xFFFFFFFF sb_commandDictionay['programIfr'].ifrIndex3 = 0x32 sb_commandDictionay['programIfr'].ifrValue3 = 0xFFFFFFFF sb_commandDictionay['programIfr'].ifrIndex4 = 0x33 sb_commandDictionay['programIfr'].ifrValue4 = 0xFFFFFFFF # Generate sb file sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'programIfr') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success # Read back the IFR values from the index 0x30 to 0x33, and verify the program values. status, results = bl.flash_read_once( sb_commandDictionay['programIfr'].ifrIndex1, 4) assert status == bootloader.status.kStatus_Success assert results[1] == sb_commandDictionay['programIfr'].ifrValue1 status, results = bl.flash_read_once( sb_commandDictionay['programIfr'].ifrIndex2, 4) assert status == bootloader.status.kStatus_Success assert results[1] == sb_commandDictionay['programIfr'].ifrValue2 status, results = bl.flash_read_once( sb_commandDictionay['programIfr'].ifrIndex3, 4) assert status == bootloader.status.kStatus_Success assert results[1] == sb_commandDictionay['programIfr'].ifrValue3 status, results = bl.flash_read_once( sb_commandDictionay['programIfr'].ifrIndex4, 4) assert status == bootloader.status.kStatus_Success assert results[1] == sb_commandDictionay['programIfr'].ifrValue4
def test_receive_sb_file_with_flash_secure(self, bl, encryptionType, dataType, mmcauDataResident): if encryptionType == 'unencrypted': # Reset the target after flash-erase-all in the setup function so that flash is in secure state. status, results = bl.reset() assert status == bootloader.status.kStatus_Success # Wait for some time to make sure the target is successfully reset. time.sleep(2) # Check the state of the flash, should be in secure status, results = bl.get_property( bootloader.properties.kPropertyTag_FlashSecurityState) assert results[0] == 1 # Initialize the sbCmdDict which will be used to generate sb file in sb_command.py. init_sbCmdDict(bl, encryptionType, dataType, mmcauDataResident) # Generate sb file if dataType == 'app_bin': sbFilePath = sb_command.generate_sb_file( bl, encryptionType, '', 'writeMemory', 'reset') elif dataType == 'string' or dataType == 'function': sbFilePath = sb_command.generate_sb_file( bl, encryptionType, '', 'writeMemory') # Send the unencrypted sb file to target. status, results = bl.receive_sb_file(sbFilePath) # Target cannot receive the unencrypted sb file when flash is secure assert status == bootloader.status.kStatusRomLdrSecureOnly # Delete the sb file os.remove(sbFilePath) elif bl.target.isEncryptionSupported == True: # 1. Program the encryption key to the specified area if encryptionType == 'zeroKeyEncrypted': key = '00000000000000000000000000000000' program_encryption_key(bl, key) elif encryptionType == 'nonZeroKeyEncrypted': # The encryption key is a string type with length of 32, each character must be 0~F. # Generate a random encryption key. keyValueFrom = '0123456789ABCDEF' key = ''.join( random.sample(keyValueFrom, 16) + random.sample(keyValueFrom, 16)) program_encryption_key(bl, key) else: raise ValueError('Invalid encryptionType parameter.') # 2. Write BCA data and mmcau data to memory. if bl.target.encryptionModuleType == encryptiontypes.kEncryptionType_LTC: pass elif bl.target.encryptionModuleType == encryptiontypes.kEncryptionType_mmCAU: # In the ROM code such as K80, L5K, though it supports the hardware security # encryption/decryption operations via CAU coprocessor which is connected to PPB, # it uses the software to implement the security encryption/decryption operations. # So we must place the mmCAU security functions to the mmcauConfigPointer address # whose value will be given in the Bootloader Configuration Area (BCA). # # # While for the flash-resident bootloader, it uses the hardware implementation if # the target supports it, so it's no need to use the mmCAU security functions and # operate the Bootloader Configuration Area (BCA). if bl.target.bootloaderType == bootsources.kBootROM_ExecuteROM: mmcauDataAddress = get_MMCAU_function_ready( bl, mmcauDataResident) elif bl.target.bootloaderType == bootsources.kBootFlash_ExecuteFlash: pass else: raise ValueError('Invalid encryptionModuleType.') # 3. Reset the target so that the BCA data can be used, and flash is in secure state. # We can use flash-erase-all and reset to set flash in secure state for ROM. status, results = bl.reset() assert status == bootloader.status.kStatus_Success # Wait for some time to make sure the target is successfully reset. time.sleep(2) # 4. Check the state of the flash, should be in secure status, results = bl.get_property( bootloader.properties.kPropertyTag_FlashSecurityState) assert results[0] == 1 # 5. Send sb file to target. # 5.1 Initialize the sbCmdDict which will be used to generate sb file in sb_command.py. init_sbCmdDict(bl, encryptionType, dataType, mmcauDataResident) # 5.2 Generate sb file if dataType == 'app_bin': sbFilePath = sb_command.generate_sb_file( bl, encryptionType, key, 'writeMemory', 'reset') elif dataType == 'string' or dataType == 'function': sbFilePath = sb_command.generate_sb_file( bl, encryptionType, key, 'writeMemory') # 5.3 Send the encrypted sb file to target. status, results = bl.receive_sb_file(sbFilePath) # 5.4 Delete the sb file os.remove(sbFilePath) if dataType == 'string': assert status == bootloader.status.kStatus_Success elif dataType == 'function': assert status == bootloader.status.kStatus_Success # Call the function will fail because flash is secure. status, results = bl.call( sbCmdDict['writeMemory'].startAddress + 1, 0) assert status == bootloader.status.kStatus_SecurityViolation elif dataType == 'app_bin': # After excuting receive-sb-file the led will blink immediately and blhost returns kStatus_AbortDataPhase. assert status == bootloader.status.kStatus_AbortDataPhase # Let led blink for some time so that we can see the correct phenomenon. time.sleep(8) # Send command to the target will have no response. status, results = bl.get_property( bootloader.properties.kPropertyTag_CurrentVersion) assert status != bootloader.status.kStatus_Success else: pytest.skip( "This case should be skipped, because current test platform doesn't support security related feature." )
def test_download_encrypted_app_with_encrypted_sb_file(self, bl): # Get the led demo that running in the qspi flash app_exists, qspiDemo = common_util.get_led_demo_path( bl, 'app_srec', running_in_qspi_flash=True) if app_exists == False: # if not exist the app file, should mark the case as SKIPPED but not FAILED print qspiDemo pytest.skip("\nDo not find the app demo srec file.") else: # Get the path of the QCB bin file path qcbBinFile = os.path.abspath( os.path.join(bl.vectorsDir, 'QSPI', kQspiConfigBlockFile)) sbCmdDict['otfadDecryption'].qspiDemo = qspiDemo # Check if the led demo code is located at 0x68001000 sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_START_ADDR = 0x68001000 # keyblob start address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_END_ADDR = 0x68001FFF # keyblob end address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].OTFAD_CTX0_CTR = "FFFFFFFFFFFFFFFF" sbCmdDict[ 'otfadDecryption'].encrypted_type_0 = 'encrypt_appSrecFile' sbCmdDict[ 'otfadDecryption'].Key_Encryption_Key = "00f1e2d3c4b5a69788796a5b4c3d2e1f" # Check if the keyBlobPointer is 0x1000 in the BCA sbCmdDict['otfadDecryption'].kek_location = 0x1000 # Enable the qspi in bd file sbCmdDict['enableQspi'].qspiConfigBlock = qcbBinFile sbCmdDict['enableQspi'].qcbLocation = 0x20000000 # Erase qspi flash in bd file sbCmdDict['flashEraseRegion'].startAddress = 0x68000000 sbCmdDict['flashEraseRegion'].endAddress = 0x68002000 # Erase the whole flash status, results = bl.flash_erase_all() assert status == bootloader.status.kStatus_Success # Generate encrypted sb file sb_file_encryption_key = '000102030405060708090a0b0c0d0e0f' sbFilePath = sb_command.generate_sb_file(bl, 'nonZeroKeyEncrypted', sb_file_encryption_key, 'enableQspi', 'flashEraseRegion', 'otfadDecryption') # Get the sb file IFR key according to the given sb_file_encryption_key key1, key2, key3, key4 = sb_command.convert_32bit_key( sb_file_encryption_key) # Program the key to IFR key = [key1, key2, key3, key4] for i in range(0, len(key)): status, results = bl.flash_program_once(0x30 + i, 4, key[i]) assert status == bootloader.status.kStatus_Success # Reset the target and let it be in secure status, results = bl.reset() assert status == bootloader.status.kStatus_Success time.sleep(2) # Check if flash is in secure status, results = bl.get_property( bootloader.properties.kPropertyTag_FlashSecurityState) assert status == bootloader.status.kStatus_Success assert results[0] == 1 # Send the encrypted sb file to target status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success # Reset the target we can see the led blinking status, results = bl.reset() assert status == bootloader.status.kStatus_Success # Let led blink for some time so that we can see the correct phenomenon. time.sleep(3) # Now communicate with bootloader, it has no response which means OTFAD decrypts the app successfully status, results = bl.get_property( bootloader.properties.kPropertyTag_CurrentVersion) assert status != bootloader.status.kStatus_Success
def test_decrypt_four_nonoverlapped_regions(self, bl): # Get the led demo that running in the qspi flash app_exists, qspiDemo = common_util.get_led_demo_path( bl, 'app_srec', running_in_qspi_flash=True) if app_exists == False: # if not exist the app file, should mark the case as SKIPPED but not FAILED print qspiDemo pytest.skip("\nDo not find the app demo srec file.") else: # Get the path of the QCB bin file path qcbBinFile = os.path.abspath( os.path.join(bl.vectorsDir, 'QSPI', kQspiConfigBlockFile)) sbCmdDict['otfadDecryption'].qspiDemo = qspiDemo # The first keyblob region. App demo is encrypted and decrypted in this region. # Check if the app demo code is located at 0x68001000. sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_START_ADDR = 0x68001000 # keyblob start address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_END_ADDR = 0x68001FFF # keyblob end address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].OTFAD_CTX0_CTR = "FFFFFFFFFFFFFFFF" sbCmdDict[ 'otfadDecryption'].encrypted_type_0 = 'encrypt_appSrecFile' # The second keyblob region sbCmdDict[ 'otfadDecryption'].OTFAD_CTX1_START_ADDR = 0x68002000 # keyblob start address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX1_END_ADDR = 0x68002FFF # keyblob end address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX1_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].OTFAD_CTX1_CTR = "FFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].encrypted_type_1 = 'encrypt_write' sbCmdDict[ 'otfadDecryption'].encrypted_data_1 = qcbBinFile # Here can be any other bin files sbCmdDict['otfadDecryption'].data_location_start_1 = sbCmdDict[ 'otfadDecryption'].OTFAD_CTX1_START_ADDR encrypt_data_size_1 = os.path.getsize( sbCmdDict['otfadDecryption'].encrypted_data_1) sbCmdDict['otfadDecryption'].data_location_end_1 = sbCmdDict[ 'otfadDecryption'].data_location_start_1 + encrypt_data_size_1 # The third keyblob region sbCmdDict[ 'otfadDecryption'].OTFAD_CTX2_START_ADDR = 0x68003000 # keyblob start address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX2_END_ADDR = 0x68003FFF # keyblob end address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX2_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].OTFAD_CTX2_CTR = "FFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].encrypted_type_2 = 'encrypt_write' sbCmdDict[ 'otfadDecryption'].encrypted_data_2 = qcbBinFile # Here can be any other bin files sbCmdDict['otfadDecryption'].data_location_start_2 = sbCmdDict[ 'otfadDecryption'].OTFAD_CTX2_START_ADDR encrypt_data_size_2 = os.path.getsize( sbCmdDict['otfadDecryption'].encrypted_data_2) sbCmdDict['otfadDecryption'].data_location_end_2 = sbCmdDict[ 'otfadDecryption'].data_location_start_2 + encrypt_data_size_2 # The fourth keyblob region sbCmdDict[ 'otfadDecryption'].OTFAD_CTX3_START_ADDR = 0x68004000 # keyblob start address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX3_END_ADDR = 0x68004FFF # keyblob end address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX3_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].OTFAD_CTX3_CTR = "FFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].encrypted_type_3 = 'encrypt_write' sbCmdDict[ 'otfadDecryption'].encrypted_data_3 = qcbBinFile # Here can be any other bin files sbCmdDict['otfadDecryption'].data_location_start_3 = sbCmdDict[ 'otfadDecryption'].OTFAD_CTX3_START_ADDR encrypt_data_size_3 = os.path.getsize( sbCmdDict['otfadDecryption'].encrypted_data_3) sbCmdDict['otfadDecryption'].data_location_end_3 = sbCmdDict[ 'otfadDecryption'].data_location_start_3 + encrypt_data_size_3 sbCmdDict[ 'otfadDecryption'].Key_Encryption_Key = "5391e2d3c4b5a69788796a5b4c3d2e1f" # Check if the keyBlobPointer is 0x1000 in the BCA sbCmdDict['otfadDecryption'].kek_location = 0x1000 # Enable the qspi in bd file sbCmdDict['enableQspi'].qspiConfigBlock = qcbBinFile sbCmdDict['enableQspi'].qcbLocation = 0x20000000 # Erase qspi flash in bd file sbCmdDict['flashEraseRegion'].startAddress = 0x68000000 sbCmdDict['flashEraseRegion'].endAddress = 0x68005000 # Generate encrypted sb file and send the sb file to target sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'enableQspi', 'flashEraseRegion', 'otfadDecryption') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success # --------------------------------------------------------------------------------------------------- # Check if the data in these four independent keyblob regions can be successfully decrypted by OTFAD. # --------------------------------------------------------------------------------------------------- # 1. Reset the target, the led will blink, which means OTFAD decrypts the first keyblob region data. status, results = bl.reset() assert status == bootloader.status.kStatus_Success time.sleep(3) # 2. Communicate with bootloader, it will have no response. status, results = bl.get_property( bootloader.properties.kPropertyTag_CurrentVersion) assert status != bootloader.status.kStatus_Success # 3. Use JLink to read data from the other three keyblob regions decrypted_data_1 = bl.target.read( sbCmdDict['otfadDecryption'].data_location_start_1, encrypt_data_size_1) decrypted_data_2 = bl.target.read( sbCmdDict['otfadDecryption'].data_location_start_2, encrypt_data_size_2) decrypted_data_3 = bl.target.read( sbCmdDict['otfadDecryption'].data_location_start_3, encrypt_data_size_3) # 4. Compare the decryption data with the pliantext with open(qcbBinFile, 'rb') as fileObj: plaintext = fileObj.read() fileObj.close() assert decrypted_data_1 == plaintext assert decrypted_data_2 == plaintext assert decrypted_data_3 == plaintext
def test_encrypt_decrypt_overlapped_region(self, bl): # Get the led demo that running in the qspi flash app_exists, qspiDemo = common_util.get_led_demo_path( bl, running_in_qspi_flash=True) if app_exists == False: # if not exist the app file, should mark the case as SKIPPED but not FAILED print qspiDemo pytest.skip("\nDo not find the app demo srec file.") else: # Get the path of the QCB bin file path qcbBinFile = os.path.abspath( os.path.join(bl.vectorsDir, 'QSPI', kQspiConfigBlockFile)) sbCmdDict['otfadDecryption'].qspiDemo = qspiDemo # Check if the led demo code is located at 0x68001000 sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_START_ADDR = 0x68001000 # keyblob start address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_END_ADDR = 0x68001FFF # keyblob end address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].OTFAD_CTX0_CTR = "FFFFFFFFFFFFFFFF" # Encrypt app demo sbCmdDict[ 'otfadDecryption'].encrypted_type_0 = 'encrypt_appSrecFile' # The second keyblob region sbCmdDict[ 'otfadDecryption'].OTFAD_CTX1_START_ADDR = 0x68002000 # keyblob start address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX1_END_ADDR = 0x68002FFF # keyblob end address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX1_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].OTFAD_CTX1_CTR = "FFFFFFFFFFFFFFFF" # Encrypt data in the overlapped region (0x68002000 ~ 0x68002FFF) sbCmdDict['otfadDecryption'].encrypted_type_1 = 'encrypt_write' sbCmdDict[ 'otfadDecryption'].encrypted_data_1 = qcbBinFile # Here can be any other bin files sbCmdDict['otfadDecryption'].data_location_start_1 = sbCmdDict[ 'otfadDecryption'].OTFAD_CTX1_START_ADDR encrypt_data_size_1 = os.path.getsize( sbCmdDict['otfadDecryption'].encrypted_data_1) sbCmdDict['otfadDecryption'].data_location_end_1 = sbCmdDict[ 'otfadDecryption'].data_location_start_1 + encrypt_data_size_1 # The third keyblob region, which is overlapped with the second keyblob region sbCmdDict[ 'otfadDecryption'].OTFAD_CTX2_START_ADDR = 0x68002000 # keyblob start address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX2_END_ADDR = 0x68003FFF # keyblob end address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX2_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].OTFAD_CTX2_CTR = "FFFFFFFFFFFFFFFF" # Encrypt data in the undefined region sbCmdDict['otfadDecryption'].encrypted_type_2 = 'encrypt_write' sbCmdDict[ 'otfadDecryption'].encrypted_data_2 = qcbBinFile # Here can be any other bin files sbCmdDict[ 'otfadDecryption'].data_location_start_2 = 0x68004000 # undefined keyblob region encrypt_data_size_2 = os.path.getsize( sbCmdDict['otfadDecryption'].encrypted_data_2) sbCmdDict['otfadDecryption'].data_location_end_2 = sbCmdDict[ 'otfadDecryption'].data_location_start_2 + encrypt_data_size_2 sbCmdDict[ 'otfadDecryption'].Key_Encryption_Key = "5391e2d3c4b5a69788796a5b4c3d2e1f" # Check if the keyBlobPointer is 0x1000 in the BCA sbCmdDict['otfadDecryption'].kek_location = 0x1000 # Enable the qspi in bd file sbCmdDict['enableQspi'].qspiConfigBlock = qcbBinFile sbCmdDict['enableQspi'].qcbLocation = 0x20000000 # Erase qspi flash in bd file sbCmdDict['flashEraseRegion'].startAddress = 0x68000000 sbCmdDict['flashEraseRegion'].endAddress = 0x68005000 # Generate encrypted sb file and send the sb file to target sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'enableQspi', 'flashEraseRegion', 'otfadDecryption') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success # ---------------------------------------------------------------------------------------------- # Check if elftosb.exe encrypts the overlapped region (will encrypt), and # check if the elftosb.exe encrypts the undefined region (will not encrypt) # ---------------------------------------------------------------------------------------------- # 1. Get the original data that will be encrypted in the overlapped region with open(sbCmdDict['otfadDecryption'].encrypted_data_1, 'rb') as fileObj: original_data_overlapped = fileObj.read() fileObj.close() # 2. Get data from the overlapped region after encryption binFile = os.path.join(bl.vectorsDir, 'read_data_from_memory.bin') status, results = bl.read_memory( sbCmdDict['otfadDecryption'].data_location_start_1, encrypt_data_size_1, binFile) assert status == bootloader.status.kStatus_Success with open(binFile, 'rb') as fileObj: encrypted_data_overlapped = fileObj.read() fileObj.close() # elftosb encrypts the overlapped region, so encrypted_data_overlapped is not equal to original_data_overlapped assert encrypted_data_overlapped != original_data_overlapped # 3. Get the original data that will be encrypted in the undefined region with open(sbCmdDict['otfadDecryption'].encrypted_data_2, 'rb') as fileObj: original_data_undefined = fileObj.read() fileObj.close() # 4. Get data from the undefined region after encryption binFile = os.path.join(bl.vectorsDir, 'read_data_from_memory.bin') status, results = bl.read_memory( sbCmdDict['otfadDecryption'].data_location_start_2, encrypt_data_size_2, binFile) assert status == bootloader.status.kStatus_Success with open(binFile, 'rb') as fileObj: encrypted_data_undefined = fileObj.read() fileObj.close() # elftosb does not encrypt the undefined region, so encrypted_data_undefined is equal to original_data_undefined assert encrypted_data_undefined == original_data_undefined # 5. Reset the target we can see the led blinking. OTFAD starts to decrypt after app running. status, results = bl.reset() assert status == bootloader.status.kStatus_Success # Let led blink for some time so that we can see the correct phenomenon. time.sleep(3) # 6. Now communicate with bootloader, it has no response which means OTFAD decrypts the app successfully status, results = bl.get_property( bootloader.properties.kPropertyTag_CurrentVersion) assert status != bootloader.status.kStatus_Success # 7. Get data from the overlapped region after decryption decrypted_data_overlapped = bl.target.read( sbCmdDict['otfadDecryption'].data_location_start_1, encrypt_data_size_1) # OTFAD does not decrypt the overlapped region, so decrypted_data_overlapped is equal to encrypted_data_overlapped assert decrypted_data_overlapped == encrypted_data_overlapped # 8. Get data from the undefined region after decryption decrypted_data_undefined = bl.target.read( sbCmdDict['otfadDecryption'].data_location_start_2, encrypt_data_size_2) # OTFAD does not decrypt the undefined region, so decrypted_data_undefined is equal to encrypted_data_undefined assert decrypted_data_undefined == encrypted_data_undefined
def test_encrypt_filled_pattern(self, bl): # Get the path of the QCB bin file path qcbBinFile = os.path.abspath( os.path.join(bl.vectorsDir, 'QSPI', kQspiConfigBlockFile)) # Only use one keyblob region qspi_config_block = os.path.abspath( os.path.join(bl.vectorsDir, 'QSPI', kQspiConfigBlockFile)) sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_START_ADDR = 0x68001000 # keyblob start address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_END_ADDR = 0x68001FFF # keyblob end address sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].OTFAD_CTX0_CTR = "FFFFFFFFFFFFFFFF" sbCmdDict['otfadDecryption'].encrypted_type_0 = 'encrypt_fill' # Encrypt the qspi config block data sbCmdDict['otfadDecryption'].encrypted_data_0 = 0x12 # filled pattern # Fill 1KB data pattern to have a test data_size = 0x400 # Let the start address matchs the keyblob start address sbCmdDict['otfadDecryption'].data_location_start_0 = sbCmdDict[ 'otfadDecryption'].OTFAD_CTX0_START_ADDR sbCmdDict['otfadDecryption'].data_location_end_0 = sbCmdDict[ 'otfadDecryption'].data_location_start_0 + data_size # Enable the qspi in bd file sbCmdDict['enableQspi'].qspiConfigBlock = qcbBinFile sbCmdDict['enableQspi'].qcbLocation = 0x20000000 # Erase qspi flash in bd file sbCmdDict['flashEraseRegion'].startAddress = 0x68000000 sbCmdDict['flashEraseRegion'].endAddress = 0x68006000 # Generate sb file according to the parameters sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'enableQspi', 'flashEraseRegion', 'otfadDecryption') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success plaintext = common_util.generate_file_according_to_filled_pattern( bl, sbCmdDict['otfadDecryption'].encrypted_data_0, 'byte', data_size) # Read back the ciphertext ciphertext = os.path.join(bl.vectorsDir, 'read_data_from_memory.bin') status, results = bl.read_memory( sbCmdDict['otfadDecryption'].data_location_start_0, data_size, ciphertext) assert status == bootloader.status.kStatus_Success # The plaintext should not be the same with the ciphertext with open(plaintext, 'rb') as plain_Obj: plain_data = plain_Obj.read() plain_Obj.close() with open(ciphertext, 'rb') as cipher_Obj: ciphter_data = cipher_Obj.read() cipher_Obj.close() assert plain_data != ciphter_data
def test_sb_reset_target(self, bl): # if app not exist, just generate reset command in sb file sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'reset') status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_AbortDataPhase
def test_sb_call_a_function_with_arg(self, bl, hasArg): ''' Step 1: Design a function, below is the code in the main.c file. ==================================== main.c (start)========================================== #include <stdio.h> #include <stdint.h> #define SysTick_BASE_ADDR 0xE000E010 #define SYST_RVR_OFFSET 0x04 #define SYST_RVR_ADDR (SysTick_BASE_ADDR + SYST_RVR_OFFSET) //This function to program the SysTick Reload Value Register (SYST_RVR), which is a 24-bit register. //Scenario 1: with one input arguement. int program_SYST_RVR_register_with_arg(unsigned int reload_value) { *((volatile uint32_t*)SYST_RVR_ADDR) = reload_value; return 0; } //Scenario 2: with no input arguement. int program_SYST_RVR_register_without_arg(void) { *((volatile uint32_t*)SYST_RVR_ADDR) = 0x123456; // Program the fix value return 0; } int main() { return 0; } ==================================== main.c (end)========================================== Step 2: Create an IAR project and add the main.c to the project. Step 3: Set the IAR Options-->Linker-->Library-->Entry symbol as the function name (i.e program_SYST_RVR_register_with_arg or program_SYST_RVR_register_without_arg) Step 4: Modify the default linker file (Options-->Linker-->Config-->Edit-->Memory Regions-->IROM1 Start: 0xA000) Step 5: Build the project and generate the out file (program_SYST_RVR_register_with_arg.out or program_SYST_RVR_register_without_arg). ''' print( "Use Jlink to read the SysTick Reload Value Register(24bits) and get the original value:" ) originalValueBinFile = bl.target.dump_memory(SYST_RVR_ADDR, 4) fileObj = file(originalValueBinFile, 'rb') data = fileObj.read() fileObj.close() originalValue = ord(data[0]) | (ord(data[1]) << 8) | ( ord(data[2]) << 16) | (ord(data[3]) << 24) print("The original value of SysTick Reload Value Register: 0x%x" % (originalValue)) if hasArg: sb_commandDictionay['call'].hasArg = True sb_commandDictionay['call'].arg = random.randint(0, 0x00ffffff) outFilePath = os.path.join( bl.vectorsDir, 'call_function', 'program_SYST_RVR_register_with_arg.out') else: sb_commandDictionay['call'].hasArg = False sb_commandDictionay['call'].arg = 0x123456 outFilePath = os.path.join( bl.vectorsDir, 'call_function', 'program_SYST_RVR_register_without_arg.out') if not os.path.exists(outFilePath): print("Cannot find the out file: %s" % outFilePath) raise ValueError("Cannot find the out file: %s" % outFilePath) else: # Initialize the dictionary sb_commandDictionay['writeMemory'].cumulativeWrite = False sb_commandDictionay['writeMemory'].data = outFilePath sb_commandDictionay['writeMemory'].dataType = 'app_out' sb_commandDictionay['flashEraseRegion'].startAddress = 0xA000 sb_commandDictionay['flashEraseRegion'].endAddress = 0xB000 # generate sb file sbFilePath = sb_command.generate_sb_file(bl, 'unencrypted', '', 'flashEraseRegion', 'writeMemory', 'call') print( "Call a function to program 0x%x to the SysTick Reload Value Register in the sb file:" % (sb_commandDictionay['call'].arg)), status, results = bl.receive_sb_file(sbFilePath) assert status == bootloader.status.kStatus_Success os.remove(sbFilePath) '''Note: Here we can use both JLink and blhost command to read the SysTick Reload Value Register, but better use JLink, because for some platforms such as L5K, this register is not in the defined regions in g_memoryMap, which is defined in memory_map_#platform.c file, so when using read-mmeory to read this register, blhost always returns kStatusMemoryRangeInvalid. ''' # Read SysTick Reload Value Register(24bits) and compare it with the input arg, should be equal. programmedValueBinFile = bl.target.dump_memory(SYST_RVR_ADDR, 4) fileObj = file(programmedValueBinFile, 'rb') data = fileObj.read() fileObj.close() programmedValue = ord(data[0]) | (ord(data[1]) << 8) | ( ord(data[2]) << 16) | (ord(data[3]) << 24) print( "After calling the function, the value of SysTick Reload Value Register is changing to 0x%x" % (programmedValue)) if programmedValue == sb_commandDictionay['call'].arg: print("0x%x == 0x%x, call the function successfully!" % (programmedValue, sb_commandDictionay['call'].arg)) testResult = True else: print("0x%x != 0x%x, call the function fail!" % (programmedValue, sb_commandDictionay['call'].arg)) testResult = False assert testResult == True print( "Use Jlink to write the original value back to the SysTick Reload Value Register(24bits):" ) bl.target.restore_memory(SYST_RVR_ADDR, originalValueBinFile)