def __init__(self, dev): ''' The constructor for the class. Parameters: dev:Device handle of the drive. ''' os_type = { 'linux2': self.linux_platform, 'linux': self.linux_platform, 'win32': self.windows_platform, 'freebsd12': self.freebsd_platform } os_type[sys.platform](dev) logging.basicConfig( filename=self.log_filename, format="%(asctime)s %(name)s (%(threadName)s) - %(message)s", level=logging.DEBUG) self.logger = logging.getLogger(self.log_filename) self.logger.debug('Start sedcfg Logger') self.psk = None self.keymanager = keymanager.KeyManager() # Build the SED object for the drive self.sed = Sed(self.devname, callbacks=self) for key, val in list(self.cred_table.items()): self.keymanager.setKey(key, val) self.BandLayout = sedbandlayout() self.BandLayout.bandauth(self) self.initial_cred = self.sed.mSID
def setUp(self, mock_class): # Creating the mock object self.sedmock = mock.MagicMock() mock_class.return_value = self.sedmock self.sedmock._cipherSuites.return_value = None # Creating the Sed object with mocked values if platform.system() == "Linux": self.sed = Sed("/dev/sd?", callbacks=self) if platform.system() == "Windows": self.sed = Sed("\\\\.\\PhysicalDrive?", callbacks=self) # The mSID value for the drive self.sed_dev = self.sed.mSID # A mocked key object value used in gen_key self.sed.range_key = range_key = 0x000008060203001 # An example payload to be signed using the drive's private key for the tperSign function self.sed.sample_string = 'hello_world' # Sample Locking Range Object Values self.sed.range_objs = ['ACE_Locking_Range1_Set_RdLocked', 'ACE_Locking_Range1_Set_WrLocked', 'ACE_Locking_Range2_Set_RdLocked'] # Mock value for device wwn self.sed.mocked_wwn = "0x5000c590b9ae78e4" # Generating a random PSID value self.sed.mocked_psid = ''.join(random.choice(string.ascii_uppercase + string.digits) for i in range(33)) # A mocked value of the tableNo used to provide Datastore table write access to the host self.sed.tableNo = 1 # A dictionary containing random port values mocked from the drive self.sed.ports_dict = {281483566710785: 1, 281483566710786: 0, 281483566710787: 1, 281483566710798: 1} # Authorities for Enterprise and Opal drives self.sed.auth_SID = "SID" self.sed.auth_Admin = "Admin1" self.sed.auth_BandMaster = "BandMaster1" self.sed.auth_Erasemaster = "EraseMaster" self.sed.auth_obj = "C_PIN_Admin1" # Valid credential self.sed.valid_cred = '22' # Invalid credential self.sed.invalid_cred = '123' # A mocked value representing the uid of the second port of the drive self.sed.port_No_2 = 281483566710786 # A mocked value representing the band number to modify/read from the drive self.sed.rangeNo = 1 # A mocked value representing the ordinate of the entry to read (integer) into the TlsPsk table. self.sed.psk = 2 # A mocked value representing the Ciphersuites in bytes self.sed.CipherSuite = b'\x00\xaa' # UID returned from the drive in bytes self.sed.uid_bytes = b'0\x82\x04;0\x82\x03#\xa0\x03\x02\x01\x02\x02\x14F+\xe2m+...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' # UID returned from a FIPS drive in bytes self.sed.uid_opal = b'U\x93\xac\x98r\x00\x00\x00d\x88\x8c)}\xa3\x01\xeb\xd7|\xe2G\xa3q%\xeb_#k\x80\xb9~\xff\x02g\x9ff\x9c\x9e\xa68]\x80\x02}q\x00(X\x04\x00\x00\x00fipsq\x01NX\x02\x00\x00\x00ivq\x02c_codecs\nencode\nq\x03X\x16\x00\x00\x00}\x08 \xc3\xbc\xc3\xbd\x05H\x14\xc2\xbf\x1b\x15\xc2\x98\xc2\x97f}\xc3\x9bq\x04X\x06\x00\x00\x00latin1q\x05\x86q\x06Rq\x07X\x03\x00\x00\x00Idsq\x08]q\t(NNNNeu.\x00\x00' # An example of data used to write to the SED Datastore self.sed.data = { 'fips': {'descriptorVersion': 'RSE3 140-2 Module', 'securityLevel': 50} , # The FIPS status of the drive. 'iv': uuid.uuid4().bytes, # initialization vector for self.sed for hashes/wrappings 'Ids': [None, None, None, None], # random keyID's for each credential }
class Sedcfg(object): ''' This is a class for performing operations on the SED drive Attributes: dev: Device handle of the drive. ''' # # WARNING! WARNING! WARNING! # This sample script uses hardcoded values for the drive credentials. # This is not a good security practice. # Change these credential values to something more secure (up to 32-bytes in length)! # cred_table = { 'SID': 'ADMIN', 'C_PIN_Admin1': 'ADMIN1', 'Admin1': 'ADMIN1', 'C_PIN_User1': 'USER1', 'User1': 'USER1', 'User2': 'USER2', 'C_PIN_User2': 'USER2', 'EraseMaster': 'ERASEMASTER', 'BandMaster0': 'BANDMASTER0', 'BandMaster1': 'BANDMASTER1', 'BandMaster2': 'BANDMASTER2' } #NOT_FIPS --> Drive is not a FIPS drive #FIPS_MODE --> Drive is a Fips drive and operating in FIPS mode #NOT_FIPS_MODE -->Drive is a Fips drive and is not operating in FIPS mode/non-deterministic Fips_status = ('NOT_FIPS', 'FIPS_MODE', 'NOT_FIPS_MODE') def __init__(self, dev): ''' The constructor for the class. Parameters: dev:Device handle of the drive. ''' os_type = { 'linux2': self.linux_platform, 'linux': self.linux_platform, 'win32': self.windows_platform, 'freebsd12': self.freebsd_platform } os_type[sys.platform](dev) logging.basicConfig( filename=self.log_filename, format="%(asctime)s %(name)s (%(threadName)s) - %(message)s", level=logging.DEBUG) self.logger = logging.getLogger(self.log_filename) self.logger.debug('Start sedcfg Logger') self.psk = None self.keymanager = keymanager.KeyManager() # Build the SED object for the drive self.sed = Sed(self.devname, callbacks=self) for key, val in list(self.cred_table.items()): self.keymanager.setKey(key, val) self.BandLayout = sedbandlayout() self.BandLayout.bandauth(self) self.initial_cred = self.sed.mSID def linux_platform(self, devname): ''' The function to initialize parameters for the linux platform. Parameters: devname:Device handle of the drive. ''' self.log_filename = os.path.join(os.path.dirname(__file__), 'sedcfg.log') self.devname = devname def windows_platform(self, devname): ''' The function to initialize parameters for the windows platform. Parameters: devname:Device handle of the drive. ''' if getattr(sys, 'frozen', False): # frozen self.log_filename = os.path.join(os.path.dirname(sys.executable), 'sedcfg.log') else: # unfrozen self.log_filename = os.path.join(os.path.dirname(__file__), 'sedcfg.log') # For Windows we need to modify the input value from PD to the physical volume # Extract PD from string and take the number value to be used and extrapolate into \\.\PhysicalDrive# if ("PD" not in devname): print("Please pass drive in as PD<drive number>") print("Example: Disk 1 is PD1") exit(1) drive_number = devname[-1:] self.devname = "\\\\.\\PhysicalDrive" + drive_number def freebsd_platform(self, devname): ''' The function to initialize parameters for the bsd platorm. Parameters: devanme:Device handle of the drive. ''' self.log_filename = os.path.join(os.path.dirname(__file__), 'sedcfg.log') self.devname = devname def TlsOperation(self, args=None): ''' The function to enable and disable TLS on the drive. Parameters: args - Commandline arguments,i.e enable/disable ''' if sys.platform == "win32": print("Tls support not provided for Windows") return False if self.BandLayout.authority[1] == 'Admin1' and self.sed.checkPIN( self.BandLayout.authority[0], self.sed.mSID) == True: print("Please perform operation changecreds before Tls enable") return False authAs = [(self.BandLayout.authority[0], None), (self.BandLayout.authority[1], None)] key = tcgSupport.getPsk(self.sed) if key == None: print("Pre-Shared Key not generated") return False toUse = self.sed.getPskEntry(0) for entryId in range(4): psk = self.sed.getPskEntry(entryId) if psk is None: print("Drive doesn't support TLS") return False if psk.Enabled == True and psk.CipherSuite == ( self.sed.cipherSuite): if args.enabledisable == 'enable': print("Tls already enabled") return True if args.enabledisable == 'disable': return self.sed.setPskEntry( toUse, authAs, Enabled=False, CipherSuite=self.sed.cipherSuite, PSK=key) if args.enabledisable == 'enable': return self.sed.setPskEntry(toUse, authAs, Enabled=True, CipherSuite=self.sed.cipherSuite, PSK=key) elif args.enabledisable == 'disable': print(" TLS already disabled on the drive") return True else: print( "Please enter your input to either enable or disable Tls on the drive" ) return False def device_identification(self): ''' The function to perform device identity attestation by validating the device certificate and digital signature Uses Tpersign method to sign an input string to return the signature. Succeeds if a drive is Seagate specific,fails otherwise ''' self.sed.fipsCompliance = self.sed.fipsCompliance() if self.sed.fipsCompliance != None: print( "Drive being tested is a FIPS drive, device identification not supported" ) return # Pull the drive certificate self.logger.debug('Obtaining Drive certificate') device_cert = self.sed.get_tperSign_cert() # Validate the drive_certificate against the root certificate identity = verifyidentity.VerifyIdentity(device_cert) identity.validate_drive_cert() # Send a string to obtain the device signature string = str(datetime.datetime.today()) self.logger.debug('Performing digital signing operation') signature = self.sed.tperSign(bytes(string, encoding='utf8')) # Validate drive signature verify = identity.validate_signature(string, signature) if verify == True: print( "Device identification successfull, drive being tested is a Seagate drive" ) else: print("Drive being tested is not a Seagate drive") return def take_ownership(self, args=None): ''' The function to take owenership of the drive by changing default Admin credentials, to create band authorities and changing credentials of the created band authorities. Parameters: args - Commandline arguments Returns: True: Successful completion of taking drive ownership. False: Failure of taking drive ownership. ''' self.logger.debug('Taking ownership of the drive') if self.sed.checkPIN(self.BandLayout.authority[0], bytes(self.sed.mSID, encoding='utf8')) == False: print( "Revert the drive to factory state,Drive ownership already taken" ) return False # Change PIN of Admin to a new PIN from default value good = self.sed.changePIN( self.BandLayout.authority[0], self.keymanager.getKey(self.BandLayout.authority[0]), (None, self.initial_cred)) if good is True: if self.BandLayout.authority[1] == 'Admin1': # Activate the Locking SP of the drive only for OPAL case if self.sed.activate(self.BandLayout.authority[0]) == False: return False self.initial_cred = tcgSupport.getCred(self.keymanager, 'SID') # Change PIN of Admin of Locking SP if self.sed.changePIN( self.BandLayout.authority[1], self.keymanager.getKey(self.BandLayout.authority[1]), (None, self.initial_cred), self.BandLayout.auth_objs[0]) == False: return False if self.enable_authority() is True: print('Credentials of the drive are changed successfully') return True return False def enable_authority(self): ''' The function to enable authorities and change their credentials. Returns: True: Enable Authority successfull. False: Failure to Enable Authority. ''' self.logger.debug('Enable Authority on the drive') # Enable two users User1 and User2 and change their password to USER1 and USER2, Bandmaster1 is enabled by default in case of Enterprise. for obj in self.BandLayout.auth_objs[3:]: if self.sed.enableAuthority(self.BandLayout.authority[1], True, obj) is True: continue else: return False # By default global range is enabled in Entperise drives if self.BandLayout.enabled_bands: if self.sed.changePIN( self.BandLayout.enabled_bands[0], self.keymanager.getKey(self.BandLayout.enabled_bands[0]), (None, self.initial_cred), self.BandLayout.enabled_bands[0]) != True: return False # Change pin of band authorities to a new value for (obj, auth) in zip(self.BandLayout.auth_objs[1:], self.BandLayout.authority[2:]): if self.BandLayout.authority[1] == 'Admin1': auth = 'Admin1' self.initial_cred = self.keymanager.getKey(auth) if self.sed.changePIN(auth, self.keymanager.getKey(obj), (None, self.initial_cred), obj) == False: return False else: continue return True def configure_bands(self, args): ''' The function to configure bands on the drive and assign bands to authorities. Parameters: args - Commandline arguments: Bandno: Bandnumber to be configured RangeStart: RangeStart value Rangelength:Rangelength value LockOnReset: True or False Returns: True: Successfull completion of configuring bands. False: Failure to configure bands. ''' self.logger.debug('Configuring bands on the drive') if self.sed.checkPIN(self.BandLayout.authority[0], self.sed.mSID) == True: print("Take ownership of the drive before configuring the drive") return False # Enable band and set ranges for band if self.BandLayout.authority[1] == 'Admin1': auth = 'Admin1' else: auth = 'BandMaster' + args.Bandno if auth == 'Admin1' and args.Bandno == '0': print("Global range not present in Opal drives") return False elif args.Bandno == '0' and args.RangeStart != None: print("Can't change range for global locking range") return False elif args.Bandno != '0' and args.RangeStart == None: print("Please provide RangeStart and RangeLength values") return False configure = self.sed.setRange(auth, int(args.Bandno), authAs=(auth, self.keymanager.getKey(auth)), RangeStart=int(args.RangeStart) if args.RangeStart is not None else None, RangeLength=int(args.RangeLength) if args.RangeLength is not None else None, ReadLockEnabled=1, WriteLockEnabled=1, LockOnReset=args.LockOnReset, ReadLocked=0, WriteLocked=0) if auth == 'Admin1' and configure is True: # Give access to users to read and write unlock range only in OPAL case, Bands are assigned to authorities by default in case of Enterprise. range_objs = [ 'ACE_Locking_Range1_Set_RdLocked', 'ACE_Locking_Range1_Set_WrLocked', 'ACE_Locking_Range2_Set_RdLocked', 'ACE_Locking_Range2_Set_WrLocked' ] if args.Bandno == '1': range_obj = range_objs[:2] else: range_obj = range_objs[2:] for objts in range_obj: ret = self.sed.enable_range_access(objts, 'User' + args.Bandno, auth) if ret == False: return False if configure == True: print('Band{} is configured'.format(args.Bandno)) return True return False def enable_fipsmode(self, args=None): ''' The function to enable FIPS mode on the drive. Returns: True: Successfull completion of enable fips. False: Failure to enable fips. ''' self.logger.debug('Enabling FIPS mode') # Retrieve FIPS status status = self.fips_status(self.sed) if status == "NOT_FIPS": return False elif status == "FIPS_MODE": return True # Check the credentials of authorities to confirm ownership for auth in self.BandLayout.authority: if self.sed.checkPIN(auth, self.sed.mSID) is True: print( "Please take the ownership of the drive before FIPS enable operation" ) return False # Check whether Locking is enabled for any of the bands if self.BandLayout.authority[1] == 'Admin1': auth, start = 'Admin1', 1 else: auth, start = 'Anybody', 0 lock_enabled = False for bandnumber in range(start, 3): locking_info, status = self.sed.getRange(bandnumber, auth) if status is True and locking_info is not None: if getattr(locking_info, 'ReadLockEnabled') == True or getattr( locking_info, 'WriteLockEnabled') == True: lock_enabled = True break if lock_enabled == False: print( "Please set ReadLockEnabled and WriteLockEnabled to True for any of the enabled bands by performing configure operation" ) return False # Disable Makers Authority if self.sed.enableAuthority('SID', False, 'Makers') == False: print("Failed to disable Makers Authority") return False # Change MinPINlength if self.sed.SSC == "Opalv2": self.authorities = { self.BandLayout.authority[1]: self.BandLayout.auth_objs[0], self.BandLayout.authority[2]: self.BandLayout.auth_objs[1], self.BandLayout.authority[3]: self.BandLayout.auth_objs[2], self.BandLayout.authority[0]: self.BandLayout.authority[0] } for auth, auth_obj in self.authorities.items(): if self.sed.setMinPINLength( auth, 4, authAs=(auth, self.keymanager.getKey(auth)), obj=auth_obj) is not True: print("Failed to set MinPINlength for the authorities") return False # Disable Firmware Download for uid in self.sed.ports.keys(): p = self.sed.getPort(uid) if p is not None and hasattr(p, 'Name') and p.Name == 'FWDownload': if p.PortLocked != True: if self.sed.setPort(uid, PortLocked=True, LockOnReset=True) == False: print("Failed to disable firmware download port") return False if self.sed.fipsApprovedMode == True: print("FIPS mode of the drive enabled successfully") return True else: print("Failed to enable FIPS mode") return False def lock_unlock_bands(self, args): ''' The function to lock and unlock the bands present on the drive Parameters: args - Command line arguments: lock/unlock: Lock/Unlock the band bandno: Bandnumber Returns: True : Successfull completion of the operation. False: Failure of the operation ''' if self.sed.checkPIN(self.BandLayout.authority[0], self.sed.mSID) == True: print( "Take ownership of the drive and configure band before lock/unlock" ) return False if args.bandno == '0' and self.BandLayout.authority[1] == 'Admin1': print("Global range not present in Opal drives") return False Range_info = self.sed.getRange(int(args.bandno), self.BandLayout.authority[1]) if Range_info == False: return False print("Band state before lock/unlock =\n{}".format(Range_info[0])) self.logger.debug('Locking/Unlocking bands on the drive') if (args.lockunlock == "lock"): lock_unlock = 1 if (Range_info[0].ReadLocked == 1): print("Band{} already in locked state".format(args.bandno)) return True elif (args.lockunlock == "unlock"): lock_unlock = 0 if (Range_info[0].ReadLocked == 0): print("Band{} already in unlocked state".format(args.bandno)) return True # Perform a lock-unlock on the range auth = 'User' + args.bandno if self.BandLayout.authority[ 1] == 'Admin1' else 'BandMaster' + args.bandno lock_unlock = self.sed.setRange(auth, int(args.bandno), authAs=(auth, self.keymanager.getKey(auth)), ReadLocked=lock_unlock, WriteLocked=lock_unlock) if lock_unlock == True: print("Band{} {}ed successfully by {}".format( args.bandno, args.lockunlock, auth)) return True print("Range not configured properly") return False def datastore(self, args): ''' The function to read/write small amount of data to the datastore on the drive. Returns: True: Successfull completion of read/write data. False: Failure to read/write data. ''' auth = self.BandLayout.authority[1] self.table_number = 0 if auth == 'Admin1' and self.sed.checkPIN('SID', self.sed.mSID): print( "Please perform operation changecreds before using the datastore" ) return False for entryId in range(4): psk = self.sed.getPskEntry(entryId) if psk is None: break if psk.Enabled == True and psk.CipherSuite == self.sed.cipherSuite: print("Please disable Tls") return False self.data = nvdata = { 'fips': self.sed.fipsCompliance, # Store the FIPS status of the drive. 'iv': uuid.uuid4( ).bytes, # initialization vector used for hashes/wrappings 'Ids': [None, None, None, None], # keyID for each credential } self.sed.data_length = (len(tcgSupport.serialize(self.data))) self.logger.debug('Reading/Writing data to the datastore on the drive') if args.readwrite == "write": if auth == 'Admin1': if self.sed.writeaccess('User1', self.table_number) == False: return False if self.sed.writeData(self.BandLayout.authority[2], self.data) == True: return True return False if args.readwrite == "read": if auth == 'Admin1': if self.sed.readaccess('User1', self.table_number) == False: return False readData = self.sed.readData(self.BandLayout.authority[2]) if readData == None: print("DataStore is empty, no data to read") return True elif readData == False: return False print(readData) return True def erase_drive(self, args): ''' The function to revert the drive back to factory state. Parameters: args - Commadline arguments. psid: PSID number of the drive Returns: True : Successfull completion of the operation. False: Failure of the operation ''' self.logger.debug('Erasing the drive') result = self.sed.revert(args.psid) if (result == True): return True else: print("Wrong PSID") return False @staticmethod def fips_status(sed): ''' The function to retrieve the FIPS compliance and FIPS operating mode from the drive Parameters: sed - SED object Returns: NOT_FIPS: Drive is not a FIPS drive FIPS_MODE: Drive is a Fips drive and operating in FIPS mode NOT_FIPS_MODE: Drive is a Fips drive and is not operating in FIPS mode/non-deterministic ''' # Checking Fips Compliance Descriptor if sed.fipsCompliance == None or sed.fipsCompliance[ "standard"] != "FIPS 140-2" and sed.fipsCompliance[ "standard"] != "FIPS 140-3": print("Drive doesn't support FIPS 140-2 or FIPS 140-3 Standard") return Sedcfg.Fips_status[0] #This uses Seagate Vendor Unique functionality, and may not be supported by other vendors #May not work on older Seagate models if sed.fipsApprovedMode is True: print("Drive operating in FIPS mode") return Sedcfg.Fips_status[1] else: return Sedcfg.Fips_status[2]
class unitTests(unittest.TestCase): ''' Class for testing the methods withing the Sed class in the tcgapi.py ''' @mock.patch('TCGstorageAPI.tcgapi.pysed.Sed') def setUp(self, mock_class): # Creating the mock object self.sedmock = mock.MagicMock() mock_class.return_value = self.sedmock self.sedmock._cipherSuites.return_value = None # Creating the Sed object with mocked values if platform.system() == "Linux": self.sed = Sed("/dev/sd?", callbacks=self) if platform.system() == "Windows": self.sed = Sed("\\\\.\\PhysicalDrive?", callbacks=self) # The mSID value for the drive self.sed_dev = self.sed.mSID # A mocked key object value used in gen_key self.sed.range_key = range_key = 0x000008060203001 # An example payload to be signed using the drive's private key for the tperSign function self.sed.sample_string = 'hello_world' # Sample Locking Range Object Values self.sed.range_objs = ['ACE_Locking_Range1_Set_RdLocked', 'ACE_Locking_Range1_Set_WrLocked', 'ACE_Locking_Range2_Set_RdLocked'] # Mock value for device wwn self.sed.mocked_wwn = "0x5000c590b9ae78e4" # Generating a random PSID value self.sed.mocked_psid = ''.join(random.choice(string.ascii_uppercase + string.digits) for i in range(33)) # A mocked value of the tableNo used to provide Datastore table write access to the host self.sed.tableNo = 1 # A dictionary containing random port values mocked from the drive self.sed.ports_dict = {281483566710785: 1, 281483566710786: 0, 281483566710787: 1, 281483566710798: 1} # Authorities for Enterprise and Opal drives self.sed.auth_SID = "SID" self.sed.auth_Admin = "Admin1" self.sed.auth_BandMaster = "BandMaster1" self.sed.auth_Erasemaster = "EraseMaster" self.sed.auth_obj = "C_PIN_Admin1" # Valid credential self.sed.valid_cred = '22' # Invalid credential self.sed.invalid_cred = '123' # A mocked value representing the uid of the second port of the drive self.sed.port_No_2 = 281483566710786 # A mocked value representing the band number to modify/read from the drive self.sed.rangeNo = 1 # A mocked value representing the ordinate of the entry to read (integer) into the TlsPsk table. self.sed.psk = 2 # A mocked value representing the Ciphersuites in bytes self.sed.CipherSuite = b'\x00\xaa' # UID returned from the drive in bytes self.sed.uid_bytes = b'0\x82\x04;0\x82\x03#\xa0\x03\x02\x01\x02\x02\x14F+\xe2m+...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' # UID returned from a FIPS drive in bytes self.sed.uid_opal = b'U\x93\xac\x98r\x00\x00\x00d\x88\x8c)}\xa3\x01\xeb\xd7|\xe2G\xa3q%\xeb_#k\x80\xb9~\xff\x02g\x9ff\x9c\x9e\xa68]\x80\x02}q\x00(X\x04\x00\x00\x00fipsq\x01NX\x02\x00\x00\x00ivq\x02c_codecs\nencode\nq\x03X\x16\x00\x00\x00}\x08 \xc3\xbc\xc3\xbd\x05H\x14\xc2\xbf\x1b\x15\xc2\x98\xc2\x97f}\xc3\x9bq\x04X\x06\x00\x00\x00latin1q\x05\x86q\x06Rq\x07X\x03\x00\x00\x00Idsq\x08]q\t(NNNNeu.\x00\x00' # An example of data used to write to the SED Datastore self.sed.data = { 'fips': {'descriptorVersion': 'RSE3 140-2 Module', 'securityLevel': 50} , # The FIPS status of the drive. 'iv': uuid.uuid4().bytes, # initialization vector for self.sed for hashes/wrappings 'Ids': [None, None, None, None], # random keyID's for each credential } def range_convert(self, kwrv): ''' Helper function to handle conversion of data specific to getRange/setRange functions ''' str_kwrv = convert(kwrv) if len(str_kwrv) == 0: return None, True if self.sed.SSC != 'Enterprise': for key in list(locking_table.keys()): str_kwrv[key] = str_kwrv[locking_table[key]] for key in list(str_kwrv.keys()): if not isinstance(key, str): del str_kwrv[key] str_kwrv['LockOnReset'] = 0 in str_kwrv['LockOnReset'] return str_kwrv def port_convert(self, kwrv): ''' Helper function for handling the conversion of data specific to port functions ''' str_kwrv = convert(kwrv) if self.sed.SSC != 'Enterprise': for key, val in portlocking_table.items(): str_kwrv[key] = str_kwrv[portlocking_table[key]] if 'LockOnReset' in str_kwrv: str_kwrv['LockOnReset'] = 0 in str_kwrv['LockOnReset'] if 'PortLocked' in kwrv: str_kwrv['PortLocked'] = bool(str_kwrv['PortLocked']) if 'UID' in str_kwrv: str_kwrv['UID'] = self.sed.port_No_2 return str_kwrv def psk_convert(self, kwrv): ''' Helper function for handling the conversion of data specific to getpsk/setpsk functions ''' str_kwrv = convert(kwrv) if self.sed.SSC == 'Opalv2': for key, val in c_tls_psk_table.items(): str_kwrv[key] = str_kwrv[c_tls_psk_table[key]] if 'CipherSuite' in kwrv: str_kwrv['CipherSuite'] = PskCipherSuites.Name(str_kwrv['CipherSuite']) return str_kwrv def test_setRange_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [1], {}) # Enterprise Test case self.assertTrue(self.sed.setRange(self.sed.auth_BandMaster, self.sed.rangeNo, authAs=(self.sed.auth_BandMaster, self.sed_dev), RangeStart=8, RangeLength=64, ReadLockEnabled=1, WriteLockEnabled=1, LockOnReset=str(True), ReadLocked=0, WriteLocked=0)) # OPAL test case self.assertTrue(self.sed.setRange(self.sed.auth_Admin, self.sed.rangeNo, authAs=(self.sed.auth_Admin, self.sed_dev), RangeStart=8, RangeLength=64, ReadLockEnabled=1, WriteLockEnabled=1, LockOnReset=str(True), ReadLocked=0, WriteLocked=0)) def test_setRange_failure(self): self.sedmock.invoke.return_value = status, rv, kwrv = (1, [], {}) # Enterprise Test case self.assertFalse(self.sed.setRange(self.sed.auth_BandMaster, self.sed.rangeNo, authAs=(self.sed.auth_BandMaster, self.sed_dev), RangeStart=8, RangeLength=64, ReadLockEnabled=1, WriteLockEnabled=1, LockOnReset=str(True), ReadLocked=0, WriteLocked=0)) # OPAL test case self.assertFalse(self.sed.setRange(self.sed.auth_Admin, self.sed.rangeNo, authAs=(self.sed.auth_Admin, self.sed_dev), RangeStart=8, RangeLength=64, ReadLockEnabled=1, WriteLockEnabled=1, LockOnReset=str(True), ReadLocked=0, WriteLocked=0)) def test_getRange_success_enterprise(self): type(self.sedmock).SSC = mock.PropertyMock(return_value='Enterprise') # kwrv contains the range object for Enterprise drives self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {'ReadLocked': 0, 'UID': '\x00\x00\x08\x02\x00\x00\x00\x02', 'CommonName': 'Locking', 'RangeLength': 64, 'ReadLockEnabled': 1, 'ActiveKey': '\x00\x00\x08\x06\x00\x00\x00\x02', 'WriteLockEnabled': 1, 'WriteLocked': 0, 'RangeStart': 8, 'LockOnReset': [1], '_AllowATAUnlock': 0, 'Name': 'Band1'}) r1, r2 = (self.sed.getRange(self.sed.rangeNo,self.sed.auth_SID,authAs=(self.sed.auth_BandMaster, self.sed_dev))) x = self.range_convert(kwrv) l1 = SedObject(x) l2 = True assert r1.Name == l1.Name assert r1.RangeStart == l1.RangeStart assert r1.RangeLength == l1.RangeLength assert r1.LockOnReset == l1.LockOnReset assert r1.ReadLockEnabled == l1.ReadLockEnabled assert r1.RangeStart == l1.RangeStart assert r1.WriteLockEnabled == l1.WriteLockEnabled assert r1.ReadLocked == l1.ReadLocked assert r1.WriteLocked == l1.WriteLocked assert r1.UID == l1.UID assert r1._AllowATAUnlock == l1._AllowATAUnlock assert r2 == l2 def test_getRange_success_opal(self): # kwrv contains the range object for Opal drives self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {0: '\x00\x00\x08\x02\x00\x03\x00\x01', 1: 'Locking_Range1', 2: '', 3: 8, 4: 64, 5: 1, 6: 1, 7: 0, 8: 0, 9: [0], 10: '\x00\x00\x08\x06\x00\x03\x00\x01', 4294901760: 0}) r1, r2 = (self.sed.getRange(self.sed.rangeNo,self.sed.auth_Admin,authAs=(self.sed.auth_Admin,self.sed_dev))) x = self.range_convert(kwrv) l1 = SedObject(x) l2 = True assert r1.Name == l1.Name assert r1.RangeStart == l1.RangeStart assert r1.RangeLength == l1.RangeLength assert r1.LockOnReset == l1.LockOnReset assert r1.ReadLockEnabled == l1.ReadLockEnabled assert r1.RangeStart == l1.RangeStart assert r1.WriteLockEnabled == l1.WriteLockEnabled assert r1.ReadLocked == l1.ReadLocked assert r1.WriteLocked == l1.WriteLocked assert r1.UID == l1.UID assert r2 == l2 def test_getRange_emptykwrv(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x00, None, {}) r1, r2 = (self.sed.getRange(self.sed.rangeNo,self.sed.auth_SID,authAs=(self.sed.auth_SID, self.sed_dev))) assert r1 == None assert r2 == True def test_getRange_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) # Enterprise Test Case self.assertFalse(self.sed.getRange(self.sed.rangeNo,self.sed.auth_SID,authAs=(self.sed.auth_BandMaster,self.sed.invalid_cred))) # Opal Test Case self.assertFalse(self.sed.getRange(self.sed.rangeNo,self.sed.auth_SID,authAs=(self.sed.auth_Admin,self.sed.invalid_cred))) def test_enable_range_access_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) for obj in self.sed.range_objs: for userNo in range(1,50): self.assertTrue(self.sed.enable_range_access(obj, 'User'+str(userNo), self.sed.auth_Admin,authAs=(self.sed.auth_Admin,self.sed_dev))) def test_enable_range_access_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (12, [], {}) for obj in self.sed.range_objs: for userNo in range(99,150): self.assertFalse(self.sed.enable_range_access(obj, 'User'+str(userNo), self.sed.auth_Admin,authAs=(self.sed.auth_Admin,self.sed_dev))) def test_erase_band_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) for bandNo in range(1,250): self.assertTrue(self.sed.erase(bandNo, authAs=(self.sed.auth_Erasemaster, self.sed_dev))) def test_erase_band_fail(self): # Status code is set to 13 which translates to NOT_AUTHORIZED self.sedmock.invoke.return_value = status, rv, kwrv = (13, None, None) # Opal Test Case self.assertFalse(self.sed.erase(self.sed.rangeNo, authAs=(self.sed.auth_Admin, self.sed_dev))) # Enterprise Test Case self.assertFalse(self.sed.erase(self.sed.rangeNo, authAs=(self.sed.auth_Erasemaster, self.sed.invalid_cred))) def test_changePIN_authority_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [1], {}) # Enterprise Test Case self.assertTrue(self.sed.changePIN(self.sed.auth_SID,self.sed.valid_cred,authAs=(self.sed.auth_SID,self.sed_dev))) # Opal Test Case self.assertTrue(self.sed.changePIN(self.sed.auth_Admin,self.sed.valid_cred, authAs=(self.sed.auth_Admin,self.sed.valid_cred), obj=self.sed.auth_obj)) def test_changePIN_authority_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) # Enterprise Test Case self.assertFalse(self.sed.changePIN(self.sed.auth_SID,self.sed.invalid_cred,authAs=(self.sed.auth_SID,self.sed.invalid_cred))) # Opal Test Case self.assertFalse(self.sed.changePIN(self.sed.auth_Admin,self.sed.invalid_cred, authAs=(self.sed.auth_Admin,self.sed.invalid_cred), obj=self.sed.auth_obj)) def test_getPort_table_emptykwrv(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [[]], {}) for uid in self.sed.ports_dict.keys(): assert (self.sed.getPort(uid,authAs=(self.sed.auth_SID, self.sed.invalid_cred))) == None def test_getPort_table_success_enterpise_without_LockOnReset(self): type(self.sedmock).SSC = mock.PropertyMock(return_value='Enterprise') # kwrv contains the port table for Enterprise drives self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {b'UID': b'\x00\x01\x00\x02\x00\x01\x00\x02', b'Name': b'FWDownload', b'LockOnReset': [], b'PortLocked': 0}) p = (self.sed.getPort(self.sed.port_No_2, authAs=(self.sed.auth_SID,self.sed.valid_cred))) x = self.port_convert(kwrv) l = SedObject(x) assert p.LockOnReset == l.LockOnReset assert p.Name == l.Name assert p.PortLocked == l.PortLocked assert p.UID == l.UID def test_getPort_table_success_enterpise_with_LockOnReset(self): type(self.sedmock).SSC = mock.PropertyMock(return_value='Enterprise') # kwrv contains the port table for Enterprise drives self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {b'UID': b'\x00\x01\x00\x02\x00\x01\x00\x03', b'Name': b'UDS', b'LockOnReset': [0], b'PortLocked': 1}) p = (self.sed.getPort(self.sed.port_No_2, authAs=(self.sed.auth_SID,self.sed.valid_cred))) x = self.port_convert(kwrv) l = SedObject(x) assert p.LockOnReset == l.LockOnReset assert p.Name == l.Name assert p.PortLocked == l.PortLocked assert p.UID == l.UID def test_getPort_table_success_opal(self): type(self.sedmock).SSC = mock.PropertyMock(return_value='Opalv2') # kwrv contains the port table for Opal drives self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {0: b'\x00\x01\x00\x02\x00\x01\x00\x02', 1: b'FWDownload', 2: [], 3: 0}) p = (self.sed.getPort(self.sed.port_No_2, authAs=(self.sed.auth_SID,self.sed.valid_cred))) x = self.port_convert(kwrv) l = SedObject(x) assert p.Name == l.Name assert p.PortLocked == l.PortLocked assert p.UID == l.UID def test_getPort_table_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) for uid in self.sed.ports_dict.keys(): self.assertFalse(self.sed.getPort(uid,authAs=(self.sed.auth_SID,self.sed.invalid_cred))) def test_setPort_state_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [1], {}) for uid in self.sed.ports_dict.keys(): self.assertTrue(self.sed.setPort(uid, authAs=(self.sed.auth_SID,self.sed.valid_cred), PortLocked=True, LockOnReset=True)) def test_setPort_state_not_authorized(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, [1], {}) for uid in self.sed.ports_dict.keys(): self.assertFalse(self.sed.setPort(uid, authAs=(self.sed.auth_SID,self.sed.invalid_cred), PortLocked=True, LockOnReset=True)) def test_setPort_state_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x12, [1], {}) for uid in self.sed.ports_dict.keys(): self.assertFalse(self.sed.setPort(uid, authAs=(self.sed.auth_SID,self.sed.invalid_cred))) def test_getAuthority_success_enabled_true(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {'Enabled':1}) self.assertTrue(self.sed.getAuthority(self.sed.auth_Admin, 'Admin2', authAs=(self.sed.auth_Admin,self.sed_dev))) def test_getAuthority_success_enabled_false(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {'Enabled':2}) self.assertFalse(self.sed.getAuthority(self.sed.auth_Admin, 'Admin2', authAs=(self.sed.auth_Admin,self.sed.invalid_cred))) def test_getAuthority_false(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, [], {'Enabled':1}) self.assertFalse(self.sed.getAuthority(self.sed.auth_Admin, 'Admin2', authAs=(self.sed.auth_Admin,self.sed.invalid_cred))) def test_enableAuthority_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [1], {}) self.assertTrue(self.sed.enableAuthority(self.sed.auth_Erasemaster,True,self.sed.auth_BandMaster,authAs=(self.sed.auth_Erasemaster,self.sed_dev))) def test_enableAuthority_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (1, [1], {}) # Enterprise Test Case self.assertFalse(self.sed.enableAuthority(self.sed.auth_BandMaster,True,self.sed.auth_BandMaster,authAs=(self.sed.auth_BandMaster,self.sed.invalid_cred))) # Opal Test Case self.assertFalse(self.sed.enableAuthority(self.sed.auth_Admin,False,self.sed.auth_BandMaster,authAs=(self.sed.auth_Erasemaster,self.sed.invalid_cred))) def test_retrieve_LockingInfo_table_success(self): # kwrv contains the LockingInfo table for Enterprise drives self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {'MaxRanges': 31, 'UID': '\x00\x00\x08\x01\x00\x00\x00\x01', 'LowestAlignedLBA': 0, 'EncryptSupport': 1, 'RowNumber': 0, 'LogicalBlockSize': 512, 'AlignmentRequired': 1, 'Version': 10, 'AlignmentGranularity': 8, 'KeysAvailableCfg': 0, 'MaxReEncryptions': 0, 'Name': 'Seagate SED'}) li = self.sed.lockingInfo() test_obj = SedObject(kwrv) assert li.LogicalBlockSize == test_obj.LogicalBlockSize assert li.MaxReEncryptions == test_obj.MaxReEncryptions assert li.EncryptSupport == test_obj.EncryptSupport assert li.AlignmentGranularity == test_obj.AlignmentGranularity assert li.AlignmentRequired == test_obj.AlignmentRequired assert li.KeysAvailableCfg == test_obj.KeysAvailableCfg assert li.MaxRanges == test_obj.MaxRanges assert li.Name == test_obj.Name assert li.RowNumber == test_obj.RowNumber assert li.Version == test_obj.Version assert li.UID == test_obj.UID def test_retrieve_LockingInfo_table_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (1, [], {}) self.assertFalse(self.sed.lockingInfo()) def test_revert_psid_plaintext_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) self.assertTrue(self.sed.revert(self.sed.mocked_psid)) def test_revert_psid_wwn_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) self.assertTrue(self.sed.revert(self.sed.mocked_wwn)) def test_revert_psid_hex_wwn_success(self): wwn = int(self.sed.mocked_wwn, 0) self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) self.assertTrue(self.sed.revert(hex(wwn))) def test_revert_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) self.assertFalse(self.sed.revert(self.sed.mocked_psid)) def test_revert_lockingSP_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) self.assertTrue(self.sed.revert_lockingSP(self.sed.valid_cred)) def test_revert_lockingSP_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) self.assertFalse(self.sed.revert_lockingSP(self.sed.invalid_cred)) def test_activate_lockingSP_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) self.assertTrue(self.sed.activate(self.sed.auth_Admin,authAs=(self.sed.auth_Admin,self.sed.valid_cred))) def test_activate_lockingSP_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) self.assertFalse(self.sed.activate(self.sed.auth_Admin,authAs=(self.sed.auth_Admin,self.sed.mSID))) def test_tperSign_payload_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [self.sed.uid_bytes], {}) tper = self.sed.tperSign(self.sed.sample_string) assert tper == rv[0] def test_tperSign_payload_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) self.assertFalse(self.sed.tperSign(self.sed.sample_string)) def test_gettperSign_cert_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [self.sed.uid_bytes], {}) tper_cert = self.sed.get_tperSign_cert() rv_bytes = bytearray(rv[0]) for i, element in reversed(list(enumerate(rv_bytes))): if element == 0: del rv_bytes[i] else: break assert tper_cert == bytearray(rv_bytes) def test_tperSign_cert_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) self.assertFalse(self.sed.get_tperSign_cert()) def test_write_access_datastore_table_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) self.assertTrue(self.sed.writeaccess("User2", self.sed.tableNo, authAs=(self.sed.auth_Admin, self.sed_dev))) def test_write_access_datastore_table_User23(self): # Failure test case when passed in with higher User## values self.sedmock.invoke.return_value = status, rv, kwrv = (1, [], {}) self.assertFalse(self.sed.writeaccess("User23", self.sed.tableNo, authAs=(self.sed.auth_Admin, self.sed.invalid_cred))) def test_write_access_datastore_table_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) self.assertFalse(self.sed.writeaccess("User1", self.sed.tableNo, authAs=(self.sed.auth_Admin, self.sed.invalid_cred))) def test_read_access_datastore_table_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) self.assertTrue(self.sed.readaccess("User1", self.sed.tableNo, authAs=(self.sed.auth_Admin, self.sed_dev))) def test_read_access_datastore_table_User32(self): # Failure test case when passed in with higher User## values self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) self.assertFalse(self.sed.readaccess("User32", self.sed.tableNo, authAs=(self.sed.auth_Admin, self.sed.invalid_cred))) def test_read_access_datastore_table_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (1, [], {}) self.assertFalse(self.sed.readaccess("User23", self.sed.tableNo, authAs=(self.sed.auth_Admin, self.sed.invalid_cred))) def test_readdata_SED_datastore_success_enterprise(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [self.sed.uid_opal], {}) read = self.sed.readData(self.sed.auth_SID,authAs=(self.sed.auth_SID,self.sed.valid_cred)) l = fromSerialized(rv[0]) assert read == l def test_read_data_SED_datastore_success_opal(self): self.sed.data_length = 97 self.sedmock.invoke.return_value = status, rv, kwrv = (0, [self.sed.uid_opal], {}) self.assertTrue(self.sed.readData('User1',authAs=('User1',self.sed.valid_cred))) def test_read_data_SED_datastore_success_emptyrv(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) read = self.sed.readData(self.sed.auth_SID,authAs=(self.sed.auth_SID,self.sed.invalid_cred)) assert read == None def test_read_data_SED_datastore_checkPIN_true(self): self.sedmock._checkPIN.return_value = True self.sedmock.invoke.return_value = status, rv, kwrv = (0, [self.sed.uid_opal], {}) self.assertTrue(self.sed.readData(self.sed.auth_SID,authAs=(self.sed.auth_SID,self.sed_dev))) def test_read_data_SED_datastore_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) self.assertFalse(self.sed.readData(self.sed.auth_SID,authAs=(self.sed.auth_SID,self.sed.invalid_cred))) def test_write_data_SED_datastore_success_enterprise(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [1], {}) self.assertTrue(self.sed.writeData(self.sed.auth_BandMaster,self.sed.data, authAs=(self.sed.auth_BandMaster,self.sed.valid_cred))) def test_write_data_SED_datastore_success_opal(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [self.sed.uid_bytes], {}) self.assertTrue(self.sed.writeData('User1',self.sed.data, authAs=('User1',self.sed.valid_cred))) def test_write_data_SED_datastore_checkPIN_true(self): self.sedmock._checkPIN.return_value = True self.sedmock.invoke.return_value = status, rv, kwrv = (0, [1], {}) self.assertTrue(self.sed.writeData(self.sed.auth_BandMaster,self.sed.data, authAs=(self.sed.auth_BandMaster, self.sed_dev))) def test_write_data_SED_datastore_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) self.assertFalse(self.sed.writeData(self.sed.auth_BandMaster,self.sed.data, authAs=(self.sed.auth_BandMaster,self.sed.invalid_cred))) def test_get_media_encryption_key_success(self): # kwrv contains the UID in bytes from the drive self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {10: b'\x00\x00\x08\x06\x00\x03\x00\x01'}) m1, m2 = self.sed.get_MEK(self.sed.rangeNo, self.sed.auth_Admin, authAs=(self.sed.auth_Admin,self.sed_dev)) l1 = SedObject(kwrv) l2 = True print(l1) def test_get_media_encryption_key_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, None) self.assertFalse(self.sed.get_MEK(self.sed.rangeNo, self.sed.auth_Admin, authAs=(self.sed.auth_Admin,self.sed.invalid_cred))) def test_genkey_secure_erase_range_success(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) self.assertTrue(self.sed.gen_key(self.sed.range_key, self.sed.auth_Admin, authAs=(self.sed.auth_Admin, self.sed_dev))) def test_genkey_secure_erase_range_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, {}) self.assertFalse(self.sed.gen_key(self.sed.range_key, self.sed.auth_Admin, authAs=(self.sed.auth_Admin, self.sed_dev))) def test_getPskEntry_success_enterprise(self): # kwrv contains the TlsPsk object with values read reflected from the TCG specification self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {b'CipherSuite': b'\x00\xaa', b'CommonName': b'', b'Enabled': 1, b'Name': b'TLS_PSK_Key0', b'UID': b'\x00\x00\x00\x1e\x00\x00\x00\x01'}) p = self.sed.getPskEntry(self.sed.psk) kwrv = self.psk_convert(kwrv) mocked_return = SedObject(kwrv) assert p.Enabled == mocked_return.Enabled assert p.CommonName == mocked_return.CommonName assert p.Name == mocked_return.Name assert p.UID == mocked_return.UID assert p.CipherSuite == mocked_return.CipherSuite def test_getPskEntry_success_opal(self): type(self.sedmock).SSC = mock.PropertyMock(return_value='Opalv2') # kwrv contains the TlsPsk object with values read reflected from the TCG specification self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {0: '\x00\x00\x00\x1e\x00\x00\x00\x01', 1: 'TLS_PSK_Key1', 2: '', 3: 0, 5: '\x00\xaa'}) p = self.sed.getPskEntry(self.sed.psk) kwrv = self.psk_convert(kwrv) mocked_return = SedObject(kwrv) assert p.Enabled == mocked_return.Enabled assert p.CommonName == mocked_return.CommonName assert p.Name == mocked_return.Name assert p.UID == mocked_return.UID def test_getPskEntry_psk_Sedobject(self): psk = {'Name':'sample'} l1 = SedObject(psk) # kwrv contains the TlsPsk object with values read reflected from the TCG specification self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {'CipherSuite': '\xff\xff', 'Enabled': 0, 'CommonName': '', 'UID': '\x00\x00\x00\x1e\x00\x00\x00\x01', 'Name': 'TLS_PSK_Key0'}) p = self.sed.getPskEntry(l1) kwrv = self.psk_convert(kwrv) mocked_return = SedObject(kwrv) assert p.Enabled == mocked_return.Enabled assert p.CommonName == mocked_return.CommonName assert p.Name == mocked_return.Name assert p.UID == mocked_return.UID assert p.CipherSuite == mocked_return.CipherSuite def test_getPskEntry_emptykwrv(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) assert (self.sed.getPskEntry(self.sed.psk)) == None def test_getPskEntry_fail(self): self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, None, {}) self.assertFalse(self.sed.getPskEntry(self.sed.psk)) def test_setPskEntry_success_with_authAs(self): authAs = [(self.sed.auth_SID, self.sed_dev), (self.sed.auth_Erasemaster, self.sed_dev)] self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) self.assertTrue(self.sed.setPskEntry(self.sed.psk, authAs=authAs, Enabled=True, CipherSuite=self.sed.CipherSuite, PSK=self.sed.uid_bytes)) def test_setPskEntry_opal(self): type(self.sedmock).SSC = mock.PropertyMock(return_value='Opalv2') authAs = [(self.sed.auth_SID, self.sed_dev), (self.sed.auth_Admin, self.sed_dev)] self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) self.assertTrue(self.sed.setPskEntry(self.sed.psk, authAs=authAs, Enabled=True, CipherSuite=self.sed.CipherSuite, PSK=self.sed.uid_bytes)) def test_setPskEntry_success_checkPIN_true(self): self.sedmock._checkPIN.return_value = True authAs = [(self.sed.auth_SID, self.sed_dev), (self.sed.auth_Erasemaster, self.sed_dev)] self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) self.assertTrue(self.sed.setPskEntry(self.sed.psk, authAs=authAs, Enabled=True, CipherSuite=self.sed.CipherSuite, PSK=self.sed.uid_bytes)) def test_setPskEntry_success_psk_SedObject(self): sample_psk_object = {'Name':'sample'} authAs = [(self.sed.auth_SID, self.sed_dev), (self.sed.auth_Erasemaster, self.sed_dev)] self.sedmock.invoke.return_value = status, rv, kwrv = (0, [], {}) l1 = SedObject(sample_psk_object) self.assertTrue(self.sed.setPskEntry(l1, authAs=authAs, Enabled=True, CipherSuite=self.sed.CipherSuite, PSK=self.sed.uid_bytes)) def test_setPskEntry_fail(self): authAs = [(self.sed.auth_SID, self.sed.invalid_cred), (self.sed.auth_Erasemaster, self.sed.invalid_cred)] self.sedmock.invoke.return_value = status, rv, kwrv = (0x01, [], None) self.assertFalse(self.sed.setPskEntry(self.sed.psk, authAs=authAs, Enabled=True, CipherSuite=self.sed.CipherSuite, PSK=self.sed.uid_bytes)) def test_getAuthas_parameter_None(self): authAs = None return_tuple = (None, None) self.assertEquals(self.sed._getAuthAs(authAs), return_tuple) def test_getAuthas_parameter_tuple(self): authAs = (self.sed.auth_SID, self.sed.valid_cred) return_tuple = (self.sed.auth_SID, self.sed.valid_cred) self.assertEquals(self.sed._getAuthAs(authAs), return_tuple) def test_getAuthas_parameter_Anybody(self): authAs = ('Anybody', self.sed.valid_cred) self.assertEquals(self.sed._getAuthAs(authAs), 'Anybody') def test_getAuthas_parameter_defAuth(self): authAs = (self.sed.auth_SID, None) return_tuple = (self.sed.auth_SID, None) self.assertEquals(self.sed._getAuthAs(authAs), return_tuple) def test_ports_level0_information(self): self.sedmock.ports.return_value = self.sed.ports_dict self.assertEquals(self.sed.ports(), self.sed.ports_dict) def test_read_fips_compliance_descriptor(self): fips_return = {'standard': 'FIPS 140-2', 'securityLevel': 50, 'hardwareVersion': '1RD17D' } self.sedmock.fipsCompliance.return_value = fips_return self.assertEquals(self.sed.fipsCompliance(), fips_return) def test_read_fips_compliance_descriptor_none(self): fips_return = None self.sedmock.fipsCompliance.return_value = fips_return self.assertEquals(self.sed.fipsCompliance(), fips_return) def test_retrieve_wwn(self): self.sedmock.wwn.return_value = wwn = self.sedmock.mocked_wwn self.assertEquals(self.sed.wwn(), wwn) def test_retrieve_mSID(self): self.sedmock.mSID.return_value = mSID = self.sedmock.sed_dev self.assertEquals(self.sed.mSID(), mSID) def test_SSC_Enterprise(self): self.sedmock.SSC.return_value = SSC = 'Enterprise' self.assertEquals(self.sed.SSC(), SSC) def test_SSC_Opal(self): self.sedmock.SSC.return_value = SSC = 'Opalv2' self.assertEquals(self.sed.SSC(), SSC) def test_hasLockedRange_bands_true(self): self.sedmock.hasLockedRange.return_value = hasLockedRange = True self.assertTrue(self.sed.hasLockedRange()) def test_hasLockedRange_bands_false(self): self.sedmock.hasLockedRange.return_value = hasLockedRange = False self.assertFalse(self.sed.hasLockedRange()) def test_fipsApprovedMode_flag_true(self): self.sedmock.fipsApprovedMode.return_value = fipsApprovedMode = True self.assertTrue(self.sed.fipsApprovedMode()) def test_fipsApprovedMode_flag_false(self): self.sedmock.fipsApprovedMode.return_value = fipsApprovedMode = False self.assertFalse(self.sed.fipsApprovedMode()) def test_current_CipherSuite_for_tls(self): self.sedmock.currentCipherSuite.return_value = self.sedmock.Ciphersuite self.assertEquals(self.sed.currentCipherSuite(), self.sedmock.Ciphersuite) def test_retrieve_max_addressable_Lba(self): self.sedmock.maxLba.return_value = maxLba = 5 self.assertEquals(self.sed.maxLba(), maxLba)