Exemplo n.º 1
0
    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
Exemplo n.º 2
0
    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
        }
Exemplo n.º 3
0
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]
Exemplo n.º 4
0
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)