Example #1
0
def main():
	skipConnection = False
	
	# If an arg is supplied and if the command doesn't require to connect to a device
	if len(sys.argv) > 1 and sys.argv[1] in nonConnectionCommands:
		skipConnection = True

	if not skipConnection:
		# HID device constructor
		mooltipass_device = mooltipass_hid_device()	
		
		# Connect to device
		if mooltipass_device.connect(True) == False:
			sys.exit(0)
			
		# Get Mooltipass Version
		version_data = mooltipass_device.getMooltipassVersionAndVariant()
		print "Mooltipass version: " + version_data[1] + ", variant: " + version_data[2] + ", " + str(version_data[0]) + "Mb of Flash"
			
		# Print Mooltipass status
		print "Mooltipass status:", mooltipass_device.getMooltipassStatus()
		print ""
	
	# See if args were passed
	if len(sys.argv) > 1:
		if sys.argv[1] == "uploadBundle":
			# extract args
			if len(sys.argv) > 2:
				filename = sys.argv[2]
			else:
				filename = None
			if len(sys.argv) > 3:
				password = sys.argv[3]
			else:
				password = None
			# start upload
			mooltipass_device.uploadBundle(password, filename, True)
			
		if sys.argv[1] == "packAndSign":
			if len(sys.argv) > 5:
				# Depending on number of args, set a new password or not
				if len(sys.argv) > 6:
					firmwareBundlePackAndSign.bundlePackAndSign(sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], sys.argv[6], True)
				else:
					firmwareBundlePackAndSign.bundlePackAndSign(sys.argv[2], sys.argv[3], sys.argv[4], None, sys.argv[5], True)					
			else:
				print "packAndSign: not enough args!"
				
		if sys.argv[1] == "packSignUpload":
			if len(sys.argv) > 5:
				# Depending on number of args, set a new password or not
				if len(sys.argv) > 6:
					bundle_gen = firmwareBundlePackAndSign.bundlePackAndSign(sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], "updatefile.img", True)
				else:
					bundle_gen = firmwareBundlePackAndSign.bundlePackAndSign(sys.argv[2], sys.argv[3], sys.argv[4], None, "updatefile.img", True)
				# Did we generate the bundle?
				if bundle_gen == True:
					if len(sys.argv) > 6:
						mooltipass_device.uploadBundle(sys.argv[6], "updatefile.img", True)
					else:
						mooltipass_device.uploadBundle(sys.argv[5], "updatefile.img", True)
			else:
				print "packAndSign: not enough args!"
				
		if sys.argv[1] == "minicheck":
			if len(sys.argv) > 7:
				mooltipass_security_check.mooltipassMiniSecCheck(mooltipass_device, sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], sys.argv[6], sys.argv[7], sys.argv[8])
			else:
				print "minicheck: not enough args!"
		
		if sys.argv[1] == "initproc":
			if version_data[2] == "mini":
				mooltipassMiniInit(mooltipass_device)
			else:
				print "Device Not Supported"
				
		if sys.argv[1] == "massprodinit":
			if version_data[2] == "mini":
				mooltipassMiniMassProdInit(mooltipass_device)
			else:
				print "Device Not Supported"		

		# Generate a mass production file 
		if sys.argv[1] == "generate_mass_prod_file":
			if len(sys.argv) == (2 + 2):
				# Only firmware hex + bootloader hex are passed as args: 0s for aes keys and uids
				print "Generating blank mass production file with 0s for AES keys and UID"
				generateFlashAndEepromHex(sys.argv[2], sys.argv[3], 12345, [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0], "newflash.hex", "neweeprom.hex", True)
				
		if sys.argv[1] == "get_serial":
			if version_data[2] == "mini":
				serial_number = mooltipass_device.getMooltipassMiniSerial()
				print "Serial number in hex:", "".join(format(x, "02x") for x in serial_number)
				print "Serial number in decimal:", serial_number[0]*16777216 + serial_number[1]*65536 + serial_number[2]*256 + serial_number[3]*1
			else:
				print "Device Not Supported"
				
		if sys.argv[1] == "get_serial_set_tutorial":
			if version_data[2] == "mini":
				serial_number = mooltipass_device.getMooltipassMiniSerial()
				print "Serial number in hex:", "".join(format(x, "02x") for x in serial_number)
				print "Serial number in decimal:", serial_number[0]*16777216 + serial_number[1]*65536 + serial_number[2]*256 + serial_number[3]*1
			else:
				print "Device Not Supported"	
			mooltipass_device.enableTutorial()
				
		if sys.argv[1] == "decrypt_mini_prod":
			if len(sys.argv) > 2:
				decryptMiniProdFile(sys.argv[2])		
			else:
				print "decrypt_mini_prod: not enough args!"
				
		if sys.argv[1] == "get_uid":
			if len(sys.argv) > 2:
				uid = mooltipass_device.getUID(sys.argv[2])
				if uid != None:
					print "UID:", "".join(format(x, "02x") for x in uid)
			else:
				print "get_uid: not enough args!"
				
		if sys.argv[1] == "read_user_db_change_nb":
			mooltipass_device.getMooltipassUserDbChangeNumber()		
				
		if sys.argv[1] == "set_user_db_change_nb":
			if len(sys.argv) > 2:
				mooltipass_device.setMooltipassUserDbChangeNumber(int(sys.argv[2]), int(sys.argv[3]))		
			else:
				print "set_user_db_change_nb: not enough args!"
				
		if sys.argv[1] == "get_free_user_slots":
			mooltipass_device.getFreeUserSlots()
			
		if sys.argv[1] == "change_login_description":
			mooltipass_device.changeLoginDescription()
			
		if sys.argv[1] == "add_credential":
			mooltipass_device.addCredential()
			
		if sys.argv[1] == "test_please_retry":
			mooltipass_device.testPleaseRetry()
			
		if sys.argv[1] == "get_card_cpz":
			mooltipass_device.getCardCpz()
			
		if sys.argv[1] == "lock":
			mooltipass_device.lock()
			
		if sys.argv[1] == "get_card_creds":
			mooltipass_device.getCardCreds()
				
		if sys.argv[1] == "set_card_login":
			if len(sys.argv) > 2:
				mooltipass_device.setCardLogin(sys.argv[2])		
			else:
				print "set_card_login: not enough args!"
				
		if sys.argv[1] == "set_card_password":
			if len(sys.argv) > 2:
				mooltipass_device.setCardPassword(sys.argv[2])		
			else:
				print "set_card_password: not enough args!"
		
		if sys.argv[1] == "get_upload_password":
			if len(sys.argv) > 3:
				AESKey2 = sys.argv[3]
				UIDReqKey = sys.argv[2]
				
				# Check Key sizes
				if len(AESKey2) != AES_KEY_SIZE*2:
					print "Wrong AES Key 2 size"
					return
				if len(UIDReqKey) != UID_REQUEST_KEY_SIZE*2:
					print "Wrong UID request key size"
					return
				
				# Convert string into arrays
				AESKey2_array = array('B', AESKey2.decode("hex"))
				
				uid = mooltipass_device.getUID(UIDReqKey)
				if uid != None:
					print "Device UID (make sure it's correct):", "".join(format(x, "02x") for x in uid)
					text_password = generateBundlePasswordUpload(version_data[1], uid, AESKey2_array)
					print "Your upload password is:",text_password
			else:
				print "get_upload_password: not enough args!"
				print "get_upload_password <UID Request Key> <AES Key 2>"
Example #2
0
def main():
    skipConnection = False

    # If an arg is supplied and if the command doesn't require to connect to a device
    if len(sys.argv) > 1 and sys.argv[1] in nonConnectionCommands:
        skipConnection = True

    if not skipConnection:
        # HID device constructor
        mooltipass_device = mooltipass_hid_device()

        # Connect to device
        if mooltipass_device.connect(True) == False:
            sys.exit(0)

        # Get Mooltipass Version
        version_data = mooltipass_device.getMooltipassVersionAndVariant()
        print "Mooltipass version: " + version_data[
            1] + ", variant: " + version_data[2] + ", " + str(
                version_data[0]) + "Mb of Flash"

        # Print Mooltipass status
        print "Mooltipass status:", mooltipass_device.getMooltipassStatus()
        print ""

    # See if args were passed
    if len(sys.argv) > 1:
        if sys.argv[1] == "uploadBundle":
            # extract args
            if len(sys.argv) > 2:
                filename = sys.argv[2]
            else:
                filename = None
            if len(sys.argv) > 3:
                password = sys.argv[3]
            else:
                password = None
            # start upload
            mooltipass_device.uploadBundle(password, filename, True)

        if sys.argv[1] == "packAndSign":
            if len(sys.argv) > 5:
                # Depending on number of args, set a new password or not
                if len(sys.argv) > 6:
                    firmwareBundlePackAndSign.bundlePackAndSign(
                        sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5],
                        sys.argv[6], True)
                else:
                    firmwareBundlePackAndSign.bundlePackAndSign(
                        sys.argv[2], sys.argv[3], sys.argv[4], None,
                        sys.argv[5], True)
            else:
                print "packAndSign: not enough args!"

        if sys.argv[1] == "packSignUpload":
            if len(sys.argv) > 5:
                # Depending on number of args, set a new password or not
                if len(sys.argv) > 6:
                    bundle_gen = firmwareBundlePackAndSign.bundlePackAndSign(
                        sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5],
                        "updatefile.img", True)
                else:
                    bundle_gen = firmwareBundlePackAndSign.bundlePackAndSign(
                        sys.argv[2], sys.argv[3], sys.argv[4], None,
                        "updatefile.img", True)
                # Did we generate the bundle?
                if bundle_gen == True:
                    if len(sys.argv) > 6:
                        mooltipass_device.uploadBundle(sys.argv[6],
                                                       "updatefile.img", True)
                    else:
                        mooltipass_device.uploadBundle(sys.argv[5],
                                                       "updatefile.img", True)
            else:
                print "packAndSign: not enough args!"

        if sys.argv[1] == "minicheck":
            if len(sys.argv) > 3:
                mooltipass_security_check.mooltipassMiniSecCheck(
                    mooltipass_device, sys.argv[2], sys.argv[3], sys.argv[4])
            else:
                print "minicheck: not enough args!"

        if sys.argv[1] == "init":
            if len(sys.argv) > 2:
                if version_data[2] == "mini":
                    mooltipassMiniInit(mooltipass_device)
                else:
                    print "Device Not Supported"
            else:
                print "init: not enough args!"

        if sys.argv[1] == "decrypt_mini_prod":
            if len(sys.argv) > 2:
                decryptMiniProdFile(sys.argv[2])
            else:
                print "decrypt_mini_prod: not enough args!"

        if sys.argv[1] == "read_user_db_change_nb":
            mooltipass_device.getMooltipassUserDbChangeNumber()

        if sys.argv[1] == "set_user_db_change_nb":
            if len(sys.argv) > 2:
                mooltipass_device.setMooltipassUserDbChangeNumber(
                    int(sys.argv[2]))
            else:
                print "set_user_db_change_nb: not enough args!"

        if sys.argv[1] == "get_free_user_slots":
            mooltipass_device.getFreeUserSlots()
Example #3
0
def main():
    skipConnection = False

    # If an arg is supplied and if the command doesn't require to connect to a device
    if len(sys.argv) > 1 and sys.argv[1] in nonConnectionCommands:
        skipConnection = True

    if not skipConnection:
        # HID device constructor
        mooltipass_device = mooltipass_hid_device()

        # Connect to device
        if mooltipass_device.connect(True) == False:
            sys.exit(0)

        # Get Mooltipass Version
        version_data = mooltipass_device.getMooltipassVersionAndVariant()
        print "Mooltipass version: " + version_data[
            1] + ", variant: " + version_data[2] + ", " + str(
                version_data[0]) + "Mb of Flash"

        # Print Mooltipass status
        print "Mooltipass status:", mooltipass_device.getMooltipassStatus()
        print ""

    # See if args were passed
    if len(sys.argv) > 1:
        if sys.argv[1] == "uploadBundle":
            # extract args
            if len(sys.argv) > 2:
                filename = sys.argv[2]
            else:
                filename = None
            if len(sys.argv) > 3:
                password = sys.argv[3]
            else:
                password = None
            # start upload
            mooltipass_device.uploadBundle(password, filename, True)

        if sys.argv[1] == "packAndSign":
            if len(sys.argv) > 5:
                # Depending on number of args, set a new password or not
                if len(sys.argv) > 6:
                    firmwareBundlePackAndSign.bundlePackAndSign(
                        sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5],
                        sys.argv[6], True)
                else:
                    firmwareBundlePackAndSign.bundlePackAndSign(
                        sys.argv[2], sys.argv[3], sys.argv[4], None,
                        sys.argv[5], True)
            else:
                print "packAndSign: not enough args!"

        if sys.argv[1] == "packSignUpload":
            if len(sys.argv) > 5:
                # Depending on number of args, set a new password or not
                if len(sys.argv) > 6:
                    bundle_gen = firmwareBundlePackAndSign.bundlePackAndSign(
                        sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5],
                        "updatefile.img", True)
                else:
                    bundle_gen = firmwareBundlePackAndSign.bundlePackAndSign(
                        sys.argv[2], sys.argv[3], sys.argv[4], None,
                        "updatefile.img", True)
                # Did we generate the bundle?
                if bundle_gen == True:
                    if len(sys.argv) > 6:
                        mooltipass_device.uploadBundle(sys.argv[6],
                                                       "updatefile.img", True)
                    else:
                        mooltipass_device.uploadBundle(sys.argv[5],
                                                       "updatefile.img", True)
            else:
                print "packAndSign: not enough args!"

        if sys.argv[1] == "minicheck":
            if len(sys.argv) > 7:
                mooltipass_security_check.mooltipassMiniSecCheck(
                    mooltipass_device, sys.argv[2], sys.argv[3], sys.argv[4],
                    sys.argv[5], sys.argv[6], sys.argv[7], sys.argv[8])
            else:
                print "minicheck: not enough args!"

        if sys.argv[1] == "initproc":
            if version_data[2] == "mini":
                mooltipassMiniInit(mooltipass_device)
            else:
                print "Device Not Supported"

        if sys.argv[1] == "massprodinit":
            if version_data[2] == "mini":
                mooltipassMiniMassProdInit(mooltipass_device)
            else:
                print "Device Not Supported"

        # Generate a mass production file
        if sys.argv[1] == "generate_mass_prod_file":
            if len(sys.argv) == (2 + 2):
                # Only firmware hex + bootloader hex are passed as args: 0s for aes keys and uids
                print "Generating blank mass production file with 0s for AES keys and UID"
                generateFlashAndEepromHex(sys.argv[2], sys.argv[3], 12345, [
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                ], [
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                ], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                                          [0, 0, 0, 0, 0, 0], "newflash.hex",
                                          "neweeprom.hex", True)

        if sys.argv[1] == "get_serial":
            if version_data[2] == "mini":
                serial_number = mooltipass_device.getMooltipassMiniSerial()
                print "Serial number in hex:", "".join(
                    format(x, "02x") for x in serial_number)
                print "Serial number in decimal:", serial_number[
                    0] * 16777216 + serial_number[1] * 65536 + serial_number[
                        2] * 256 + serial_number[3] * 1
            else:
                print "Device Not Supported"

        if sys.argv[1] == "decrypt_mini_prod":
            if len(sys.argv) > 2:
                decryptMiniProdFile(sys.argv[2])
            else:
                print "decrypt_mini_prod: not enough args!"

        if sys.argv[1] == "get_uid":
            if len(sys.argv) > 2:
                uid = mooltipass_device.getUID(sys.argv[2])
                if uid != None:
                    print "UID:", "".join(format(x, "02x") for x in uid)
            else:
                print "decrypt_mini_prod: not enough args!"

        if sys.argv[1] == "read_user_db_change_nb":
            mooltipass_device.getMooltipassUserDbChangeNumber()

        if sys.argv[1] == "set_user_db_change_nb":
            if len(sys.argv) > 2:
                mooltipass_device.setMooltipassUserDbChangeNumber(
                    int(sys.argv[2]), int(sys.argv[3]))
            else:
                print "set_user_db_change_nb: not enough args!"

        if sys.argv[1] == "get_free_user_slots":
            mooltipass_device.getFreeUserSlots()

        if sys.argv[1] == "change_login_description":
            mooltipass_device.changeLoginDescription()

        if sys.argv[1] == "add_credential":
            mooltipass_device.addCredential()

        if sys.argv[1] == "test_please_retry":
            mooltipass_device.testPleaseRetry()

        if sys.argv[1] == "get_card_cpz":
            mooltipass_device.getCardCpz()

        if sys.argv[1] == "lock":
            mooltipass_device.lock()
def mooltipassMiniSecCheck(mooltipass_device, old_firmware, new_firmware, graphics_bundle):	
	# Check for valid firmware
	if not os.path.isfile(old_firmware):
		print "Wrong path to old firmware"
		return
		
	# Check for valid firmware
	if not os.path.isfile(new_firmware):
		print "Wrong path to new firmware"
		return	

	# Check for private key
	if not os.path.isfile("key.bin"):
		print "Couldn't find private key!"
		return
		
	# Check for export folder
	if not os.path.isdir("export"):
		print "Couldn't find export folder"
		return
		
	# Check versions
	old_firmware_version = mpmSecGetVersionNumberFromHex(old_firmware)
	new_firmware_version = mpmSecGetVersionNumberFromHex(new_firmware)
	print "Old FW version: " + old_firmware_version + ", new FW version: " + new_firmware_version
	if old_firmware_version > new_firmware_version:
		print "New FW version is older than old FW version!"
		return
		
	# Read private key
	# to fix! we don't use rsa anymore!
	#key = RSA.importKey(mpmSecPickleRead("key.bin"))
	
	# Ask user to choose export file
	file_list = glob.glob("export/*.txt")
	if len(file_list) == 0:
		print "No init file available!"
		return False
	elif len(file_list) == 1:
		print "Using init file", file_list[0]
		initdata = mpmSecPickleRead(file_list[0])
	else:
		for i in range(0, len(file_list)):
			print str(i) + ": " + file_list[i]
		picked_file = raw_input("Choose file: ")
		if int(picked_file) >= len(file_list):
			print "Out of bounds"
			return False
		else:
			initdata = mpmSecPickleRead(file_list[int(picked_file)])
	
	# Decrypt init data
	decrypted_data = key.decrypt(initdata)
	items = decrypted_data.split('|')
	mooltipass_id = items[0]
	mooltipass_aes_key1 = items[1]
	mooltipass_aes_key2 = items[2]
	mooltipass_req_uid_key = items[3]
	mooltipass_uid = items[4].strip()
	print "MPM ID: " + mooltipass_id 
	print "AES KEY 1: " + mooltipass_aes_key1 
	print "AES KEY 2: " + mooltipass_aes_key2
	print "REQ KEY: " + mooltipass_req_uid_key
	print "UID: " + mooltipass_uid
	
	# Start requesting random data from the MP
	rand_aes_key1 = array('B')
	rand_aes_key2 = array('B')
	rand_req_uid_key = array('B')
	set_mooltipass_password_random_payload = array('B')
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_RANDOM_NUMBER, 0, None))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	rand_aes_key1.extend(data[0:32])
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_RANDOM_NUMBER, 0, None))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	rand_aes_key2.extend(data[0:32])
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_RANDOM_NUMBER, 0, None))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	rand_req_uid_key.extend(data[DATA_INDEX:DATA_INDEX+16])
	set_mooltipass_password_random_payload.extend(rand_aes_key1)
	set_mooltipass_password_random_payload.extend(rand_aes_key2[0:30])
	rand_aes_key1_string = "".join(format(x, "02x") for x in rand_aes_key1)
	rand_aes_key2_string = "".join(format(x, "02x") for x in rand_aes_key2)
	
	# Test - set UID
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_SET_UID, 22, [0]*22))
	if mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()[DATA_INDEX] == 0x01:
		print "FAIL - Other UID set!"
	else:
		print "OK - Couldn't set new UID"
		
	# Test - Get UID with erroneous req key
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_UID, 16, rand_req_uid_key))
	data = mooltipass_device.getInternalDevice().receiveHidPacket()
	if data[LEN_INDEX] == 0x01:
		print "OK - Couln't fetch UID with random key"
	else:
		print "FAIL - Fetched UID with random key"
	
	# Test - Get UID with good req key
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_UID, 16, array('B', mooltipass_req_uid_key.decode("hex"))))
	data = mooltipass_device.getInternalDevice().receiveHidPacket()
	if data[LEN_INDEX] == 0x01:
		print "FAIL - Couln't fetch UID"
	else:
		print "OK - Fetched UID"
		if data[DATA_INDEX:DATA_INDEX+6] == array('B', mooltipass_uid.decode("hex")):
			print "OK - UID fetched is correct!"
		else:
			print "FAIL - UID fetched is different than the one provided!"
			print data[DATA_INDEX:DATA_INDEX+6], "instead of", array('B', mooltipass_uid.decode("hex"))
	
	# Test - Set New AES KEY 1 & KEY 2		
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_SET_BOOTLOADER_PWD, 62, set_mooltipass_password_random_payload))
	if mooltipass_device.getInternalDevice().receiveHidPacket()[DATA_INDEX] == 0x01:
		print "FAIL - New Mooltipass password was set"
	else:
		print "OK - Couldn't set new Mooltipass password"
		
	# Todo: implement password upload check
		
	# Test nominal firmware update with good aes key and good password, no new key flag
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, mooltipass_aes_key1, None, "updatefile.img", False)
	mooltipass_device.uploadBundle("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "OK - Same firmware upload with good AES key 1 & AES key 2 - no new key flag"
	else:
		print "FAIL - Same firmware upload with good AES key 1 & AES key 2 - no new key flag"
	# Still mooltipass_aes_key1
		
	# Test nominal firmware update with good aes key and good password 
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, mooltipass_aes_key1, rand_aes_key1_string, "updatefile.img", False)
	mooltipass_device.uploadBundle("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "OK - Same firmware upload with good AES key 1 & AES key 2"
	else:
		print "FAIL - Same firmware upload with good AES key 1 & AES key 2"
	# Changed to rand_aes_key1_string
		
	# Test nominal firmware update with bad aes key and good password 
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, mooltipass_aes_key1, rand_aes_key1_string, "updatefile.img", False)
	mooltipass_device.uploadBundle("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "FAIL - Same firmware upload with bad AES key 1 & good AES key 2"
	else:
		print "OK - Same firmware upload with bad AES key 1 & good AES key 2"
	# Still rand_aes_key1_string
		
	# Test nominal firmware update with good aes key and good password 
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, new_firmware, rand_aes_key1_string, mooltipass_aes_key1, "updatefile.img", False)
	mooltipass_device.uploadBundle("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "OK - Newer firmware upload with good AES key 1 & AES key 2"
	else:
		print "FAIL - Newer firmware upload with good AES key 1 & AES key 2"
	# Changed to mooltipass_aes_key1
		
	# Test nominal firmware update with good aes key and good password but older firmware
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, mooltipass_aes_key1, mooltipass_aes_key1, "updatefile.img", False)
	mooltipass_device.uploadBundle("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "FAIL - Older firmware upload with good AES key 1 & AES key 2"
	else:
		print "OK - Older firmware upload with good AES key 1 & AES key 2"
	# Still mooltipass_aes_key1
	
	# Timeout test for media upload
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_IMPORT_MEDIA_START, 62, [0]*62))
	print "Testing timeout... please wait 60 seconds"
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	print "OK - Timeout Test"
	
	
def mooltipassMiniSecCheck(mooltipass_device, old_firmware, new_firmware, graphics_bundle, AESKey1, AESKey2, UIDReqKey, UIDKey):	
	# Check for valid firmware
	if not os.path.isfile(old_firmware):
		print "Wrong path to old firmware"
		return
		
	# Check for valid firmware
	if not os.path.isfile(new_firmware):
		print "Wrong path to new firmware"
		return	
		
	# Check versions
	old_firmware_version = mpmSecGetVersionNumberFromHex(old_firmware)
	new_firmware_version = mpmSecGetVersionNumberFromHex(new_firmware)
	print "Old FW version: " + old_firmware_version + ", new FW version: " + new_firmware_version
	if old_firmware_version > new_firmware_version:
		print "New FW version is older than old FW version!"
		return
		
	# Check Key sizes
	if len(AESKey1) != AES_KEY_SIZE*2:
		print "Wrong AES Key 1 size"
		return
	if len(AESKey2) != AES_KEY_SIZE*2:
		print "Wrong AES Key 2 size"
		return
	if len(UIDReqKey) != UID_REQUEST_KEY_SIZE*2:
		print "Wrong UID request key size"
		return
	if len(UIDKey) != UID_KEY_SIZE*2:
		print "Wrong UID key size"
		return
	
	# Convert string into arrays
	AESKey1_array = array('B', AESKey1.decode("hex"))
	AESKey2_array = array('B', AESKey2.decode("hex"))
	UIDReqKey_array = array('B', UIDReqKey.decode("hex"))
	UIDKey_array = array('B', UIDKey.decode("hex"))
	
	# Start requesting random data from the MP
	print "Fetching random numbers..."
	rand_aes_key1 = array('B')
	rand_aes_key2 = array('B')
	rand_req_uid_key = array('B')
	set_mooltipass_password_random_payload = array('B')
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_RANDOM_NUMBER, 0, None))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	rand_aes_key1.extend(data[0:AES_KEY_SIZE])
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_RANDOM_NUMBER, 0, None))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	rand_aes_key2.extend(data[0:AES_KEY_SIZE])
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_RANDOM_NUMBER, 0, None))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	rand_req_uid_key.extend(data[DATA_INDEX:DATA_INDEX+UID_REQUEST_KEY_SIZE])
	set_mooltipass_password_random_payload.extend(rand_aes_key1)
	set_mooltipass_password_random_payload.extend(rand_aes_key2[0:30])
	rand_aes_key1_string = "".join(format(x, "02x") for x in rand_aes_key1)
	rand_aes_key2_string = "".join(format(x, "02x") for x in rand_aes_key2)
	print "Starting test, please make sure a card is inserted in reverse inside the mini!"
	
	# Set read timeouts
	mooltipass_device.getInternalDevice().setReadTimeout(3333)
	
	# Test - set UID
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_SET_UID, (UID_REQUEST_KEY_SIZE+UID_KEY_SIZE), [0]*(UID_REQUEST_KEY_SIZE+UID_KEY_SIZE)))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	if data == None or data[DATA_INDEX] != 0x01:
		print "OK - Couldn't set new UID"
	else:
		print "FAIL - Other UID set!"
		
	# Test - Get UID with erroneous req key
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_UID, UID_REQUEST_KEY_SIZE, rand_req_uid_key))
	data = mooltipass_device.getInternalDevice().receiveHidPacket()
	if data[LEN_INDEX] == 0x01:
		print "OK - Couln't fetch UID with random key"
	else:
		print "FAIL - Fetched UID with random key"
	
	# Test - Get UID with good req key
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_UID, UID_REQUEST_KEY_SIZE, UIDReqKey_array))
	data = mooltipass_device.getInternalDevice().receiveHidPacket()
	if data[LEN_INDEX] == 0x01:
		print "FAIL - Couln't fetch UID"
	else:
		print "OK - Fetched UID"
		if data[DATA_INDEX:DATA_INDEX+6] == UIDKey_array:
			print "OK - UID fetched is correct!"
		else:
			print "FAIL - UID fetched is different than the one provided!"
			print data[DATA_INDEX:DATA_INDEX+6], "instead of", UIDKey_array
	
	# Test - Set New AES KEY 1 & KEY 2		
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_SET_BOOTLOADER_PWD, 62, set_mooltipass_password_random_payload))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	if data == None or data[DATA_INDEX] != 0x01:
		print "OK - Couldn't set new Mooltipass password"
	else:
		print "FAIL - New Mooltipass password was set"
		
	# Set read timeouts
	mooltipass_device.getInternalDevice().setReadTimeout(130000)
		
	# Test bundle upload with wrong password
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, AESKey1, None, "updatefile.img", False)
	result = mooltipass_device.uploadBundle("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "updatefile.img", False)
	if result == False:
		print "OK - Couldn't start bundle upload with wrong password"
	else:
		print "FAIL - Could start bundle upload with wrong password"
	
	# Generate password for bundle upload
	text_password = generateBundlePasswordUpload(mooltipass_device.getMooltipassVersionAndVariant()[1], UIDKey_array, AESKey2_array)
		
	# Test nominal firmware update with good aes key and good password, no new key flag
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, AESKey1, None, "updatefile.img", False)
	print "Please accept prompt on the device"
	mooltipass_device.uploadBundle(text_password, "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "OK - Same firmware upload with good AES key 1 & AES key 2 - no new key flag"
	else:
		print "FAIL - Same firmware upload with good AES key 1 & AES key 2 - no new key flag"
	# Still AESKey1
	
	# Generate password for bundle upload
	text_password = generateBundlePasswordUpload(mooltipass_device.getMooltipassVersionAndVariant()[1], UIDKey_array, AESKey2_array)
		
	# Test nominal firmware update with good aes key and good password 
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, AESKey1, rand_aes_key1_string, "updatefile.img", False)
	print "Please accept prompt on the device"
	mooltipass_device.uploadBundle(text_password, "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "OK - Same firmware upload with good AES key 1 & AES key 2"
	else:
		print "FAIL - Same firmware upload with good AES key 1 & AES key 2"
	# Changed to rand_aes_key1_string
	
	# Generate password for bundle upload
	text_password = generateBundlePasswordUpload(mooltipass_device.getMooltipassVersionAndVariant()[1], UIDKey_array, AESKey2_array)
		
	# Test nominal firmware update with bad aes key and good password 
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, AESKey1, rand_aes_key1_string, "updatefile.img", False)
	print "Please accept prompt on the device"
	mooltipass_device.uploadBundle(text_password, "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	print "Don't forget to scroll a little to pass the tutorial, then wait a few seconds"
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "FAIL - Same firmware upload with bad AES key 1 & good AES key 2"
	else:
		print "OK - Same firmware upload with bad AES key 1 & good AES key 2"
	# Still rand_aes_key1_string
	
	# Generate password for bundle upload
	text_password = generateBundlePasswordUpload(mooltipass_device.getMooltipassVersionAndVariant()[1], UIDKey_array, AESKey2_array)
		
	# Test nominal firmware update with good aes key and good password 
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, new_firmware, rand_aes_key1_string, AESKey1, "updatefile.img", False)
	print "Please accept prompt on the device (click twice after a few seconds)"
	mooltipass_device.uploadBundle(text_password, "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "OK - Newer firmware upload with good AES key 1 & AES key 2"
	else:
		print "FAIL - Newer firmware upload with good AES key 1 & AES key 2"
	# Changed back to AESKey1
	
	# Generate password for bundle upload
	text_password = generateBundlePasswordUpload(mooltipass_device.getMooltipassVersionAndVariant()[1], UIDKey_array, AESKey2_array)
		
	# Test nominal firmware update with good aes key and good password but older firmware
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, AESKey1, AESKey1, "updatefile.img", False)
	print "Please accept prompt on the device"
	mooltipass_device.uploadBundle(text_password, "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	print "Don't forget to scroll a little to pass the tutorial, then wait a few seconds"
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "FAIL - Older firmware upload with good AES key 1 & AES key 2"
	else:
		print "OK - Older firmware upload with good AES key 1 & AES key 2"
	# Still AESKey1
		
	# Test nominal firmware update with good aes key and good password
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, new_firmware, AESKey1, None, "updatefile.img", False)
	print "Please accept prompt on the device (click twice after a few seconds)"
	mooltipass_device.uploadBundle(text_password, "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "OK - Same firmware upload with good AES key 1 & AES key 2"
	else:
		print "FAIL - Same firmware upload with good AES key 1 & AES key 2"
	# Still AESKey1
	
	# Timeout test for media upload
	text_password = generateBundlePasswordUpload(mooltipass_device.getMooltipassVersionAndVariant()[1], UIDKey_array, AESKey2_array)
	password = array('B', text_password.decode("hex"))
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_IMPORT_MEDIA_START, MINI_DEVICE_PASSWORD_SIZE, password))
	print "Please accept prompt on the device (click twice after a few seconds)"
	print "Testing timeout... please wait 60 seconds"
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	print "OK - Timeout Test"
	
	
def mooltipassMiniSecCheck(mooltipass_device, old_firmware, new_firmware,
                           graphics_bundle):
    # Check for valid firmware
    if not os.path.isfile(old_firmware):
        print "Wrong path to old firmware"
        return

    # Check for valid firmware
    if not os.path.isfile(new_firmware):
        print "Wrong path to new firmware"
        return

    # Check for private key
    if not os.path.isfile("key.bin"):
        print "Couldn't find private key!"
        return

    # Check for export folder
    if not os.path.isdir("export"):
        print "Couldn't find export folder"
        return

    # Check versions
    old_firmware_version = mpmSecGetVersionNumberFromHex(old_firmware)
    new_firmware_version = mpmSecGetVersionNumberFromHex(new_firmware)
    print "Old FW version: " + old_firmware_version + ", new FW version: " + new_firmware_version
    if old_firmware_version > new_firmware_version:
        print "New FW version is older than old FW version!"
        return

    # Read private key
    # to fix! we don't use rsa anymore!
    #key = RSA.importKey(mpmSecPickleRead("key.bin"))

    # Ask user to choose export file
    file_list = glob.glob("export/*.txt")
    if len(file_list) == 0:
        print "No init file available!"
        return False
    elif len(file_list) == 1:
        print "Using init file", file_list[0]
        initdata = mpmSecPickleRead(file_list[0])
    else:
        for i in range(0, len(file_list)):
            print str(i) + ": " + file_list[i]
        picked_file = raw_input("Choose file: ")
        if int(picked_file) >= len(file_list):
            print "Out of bounds"
            return False
        else:
            initdata = mpmSecPickleRead(file_list[int(picked_file)])

    # Decrypt init data
    decrypted_data = key.decrypt(initdata)
    items = decrypted_data.split('|')
    mooltipass_id = items[0]
    mooltipass_aes_key1 = items[1]
    mooltipass_aes_key2 = items[2]
    mooltipass_req_uid_key = items[3]
    mooltipass_uid = items[4].strip()
    print "MPM ID: " + mooltipass_id
    print "AES KEY 1: " + mooltipass_aes_key1
    print "AES KEY 2: " + mooltipass_aes_key2
    print "REQ KEY: " + mooltipass_req_uid_key
    print "UID: " + mooltipass_uid

    # Start requesting random data from the MP
    rand_aes_key1 = array('B')
    rand_aes_key2 = array('B')
    rand_req_uid_key = array('B')
    set_mooltipass_password_random_payload = array('B')
    mooltipass_device.getInternalDevice().sendHidPacket(
        mpmSecGetPacketForCommand(CMD_GET_RANDOM_NUMBER, 0, None))
    data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
    rand_aes_key1.extend(data[0:32])
    mooltipass_device.getInternalDevice().sendHidPacket(
        mpmSecGetPacketForCommand(CMD_GET_RANDOM_NUMBER, 0, None))
    data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
    rand_aes_key2.extend(data[0:32])
    mooltipass_device.getInternalDevice().sendHidPacket(
        mpmSecGetPacketForCommand(CMD_GET_RANDOM_NUMBER, 0, None))
    data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
    rand_req_uid_key.extend(data[DATA_INDEX:DATA_INDEX + 16])
    set_mooltipass_password_random_payload.extend(rand_aes_key1)
    set_mooltipass_password_random_payload.extend(rand_aes_key2[0:30])
    rand_aes_key1_string = "".join(format(x, "02x") for x in rand_aes_key1)
    rand_aes_key2_string = "".join(format(x, "02x") for x in rand_aes_key2)

    # Test - set UID
    mooltipass_device.getInternalDevice().sendHidPacket(
        mpmSecGetPacketForCommand(CMD_SET_UID, 22, [0] * 22))
    if mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout(
    )[DATA_INDEX] == 0x01:
        print "FAIL - Other UID set!"
    else:
        print "OK - Couldn't set new UID"

    # Test - Get UID with erroneous req key
    mooltipass_device.getInternalDevice().sendHidPacket(
        mpmSecGetPacketForCommand(CMD_GET_UID, 16, rand_req_uid_key))
    data = mooltipass_device.getInternalDevice().receiveHidPacket()
    if data[LEN_INDEX] == 0x01:
        print "OK - Couln't fetch UID with random key"
    else:
        print "FAIL - Fetched UID with random key"

    # Test - Get UID with good req key
    mooltipass_device.getInternalDevice().sendHidPacket(
        mpmSecGetPacketForCommand(
            CMD_GET_UID, 16, array('B', mooltipass_req_uid_key.decode("hex"))))
    data = mooltipass_device.getInternalDevice().receiveHidPacket()
    if data[LEN_INDEX] == 0x01:
        print "FAIL - Couln't fetch UID"
    else:
        print "OK - Fetched UID"
        if data[DATA_INDEX:DATA_INDEX + 6] == array(
                'B', mooltipass_uid.decode("hex")):
            print "OK - UID fetched is correct!"
        else:
            print "FAIL - UID fetched is different than the one provided!"
            print data[DATA_INDEX:DATA_INDEX + 6], "instead of", array(
                'B', mooltipass_uid.decode("hex"))

    # Test - Set New AES KEY 1 & KEY 2
    mooltipass_device.getInternalDevice().sendHidPacket(
        mpmSecGetPacketForCommand(CMD_SET_BOOTLOADER_PWD, 62,
                                  set_mooltipass_password_random_payload))
    if mooltipass_device.getInternalDevice().receiveHidPacket(
    )[DATA_INDEX] == 0x01:
        print "FAIL - New Mooltipass password was set"
    else:
        print "OK - Couldn't set new Mooltipass password"

    # Todo: implement password upload check

    # Test nominal firmware update with good aes key and good password, no new key flag
    firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware,
                                                mooltipass_aes_key1, None,
                                                "updatefile.img", False)
    mooltipass_device.uploadBundle(
        "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "updatefile.img", False)
    mpmSecWaitForDeviceDisconRecon(mooltipass_device)
    usr_answer = raw_input("Tutorial displayed? [y/n]: ")
    if usr_answer == "y":
        print "OK - Same firmware upload with good AES key 1 & AES key 2 - no new key flag"
    else:
        print "FAIL - Same firmware upload with good AES key 1 & AES key 2 - no new key flag"
    # Still mooltipass_aes_key1

    # Test nominal firmware update with good aes key and good password
    firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware,
                                                mooltipass_aes_key1,
                                                rand_aes_key1_string,
                                                "updatefile.img", False)
    mooltipass_device.uploadBundle(
        "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "updatefile.img", False)
    mpmSecWaitForDeviceDisconRecon(mooltipass_device)
    usr_answer = raw_input("Tutorial displayed? [y/n]: ")
    if usr_answer == "y":
        print "OK - Same firmware upload with good AES key 1 & AES key 2"
    else:
        print "FAIL - Same firmware upload with good AES key 1 & AES key 2"
    # Changed to rand_aes_key1_string

    # Test nominal firmware update with bad aes key and good password
    firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware,
                                                mooltipass_aes_key1,
                                                rand_aes_key1_string,
                                                "updatefile.img", False)
    mooltipass_device.uploadBundle(
        "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "updatefile.img", False)
    mpmSecWaitForDeviceDisconRecon(mooltipass_device)
    usr_answer = raw_input("Tutorial displayed? [y/n]: ")
    if usr_answer == "y":
        print "FAIL - Same firmware upload with bad AES key 1 & good AES key 2"
    else:
        print "OK - Same firmware upload with bad AES key 1 & good AES key 2"
    # Still rand_aes_key1_string

    # Test nominal firmware update with good aes key and good password
    firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, new_firmware,
                                                rand_aes_key1_string,
                                                mooltipass_aes_key1,
                                                "updatefile.img", False)
    mooltipass_device.uploadBundle(
        "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "updatefile.img", False)
    mpmSecWaitForDeviceDisconRecon(mooltipass_device)
    usr_answer = raw_input("Tutorial displayed? [y/n]: ")
    if usr_answer == "y":
        print "OK - Newer firmware upload with good AES key 1 & AES key 2"
    else:
        print "FAIL - Newer firmware upload with good AES key 1 & AES key 2"
    # Changed to mooltipass_aes_key1

    # Test nominal firmware update with good aes key and good password but older firmware
    firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware,
                                                mooltipass_aes_key1,
                                                mooltipass_aes_key1,
                                                "updatefile.img", False)
    mooltipass_device.uploadBundle(
        "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "updatefile.img", False)
    mpmSecWaitForDeviceDisconRecon(mooltipass_device)
    usr_answer = raw_input("Tutorial displayed? [y/n]: ")
    if usr_answer == "y":
        print "FAIL - Older firmware upload with good AES key 1 & AES key 2"
    else:
        print "OK - Older firmware upload with good AES key 1 & AES key 2"
    # Still mooltipass_aes_key1

    # Timeout test for media upload
    mooltipass_device.getInternalDevice().sendHidPacket(
        mpmSecGetPacketForCommand(CMD_IMPORT_MEDIA_START, 62, [0] * 62))
    print "Testing timeout... please wait 60 seconds"
    mpmSecWaitForDeviceDisconRecon(mooltipass_device)
    print "OK - Timeout Test"
def mooltipassMiniSecCheck(mooltipass_device, old_firmware, new_firmware, graphics_bundle, AESKey1, AESKey2, UIDReqKey, UIDKey):	
	# Check for valid firmware
	if not os.path.isfile(old_firmware):
		print "Wrong path to old firmware"
		return
		
	# Check for valid firmware
	if not os.path.isfile(new_firmware):
		print "Wrong path to new firmware"
		return	
		
	# Check versions
	old_firmware_version = mpmSecGetVersionNumberFromHex(old_firmware)
	new_firmware_version = mpmSecGetVersionNumberFromHex(new_firmware)
	print "Old FW version: " + old_firmware_version + ", new FW version: " + new_firmware_version
	if old_firmware_version > new_firmware_version:
		print "New FW version is older than old FW version!"
		return
		
	# Check Key sizes
	if len(AESKey1) != AES_KEY_SIZE*2:
		print "Wrong AES Key 1 size"
		return
	if len(AESKey2) != AES_KEY_SIZE*2:
		print "Wrong AES Key 2 size"
		return
	if len(UIDReqKey) != UID_REQUEST_KEY_SIZE*2:
		print "Wrong UID request key size"
		return
	if len(UIDKey) != UID_KEY_SIZE*2:
		print "Wrong UID key size"
		return
	
	# Convert string into arrays
	AESKey1_array = array('B', AESKey1.decode("hex"))
	AESKey2_array = array('B', AESKey2.decode("hex"))
	UIDReqKey_array = array('B', UIDReqKey.decode("hex"))
	UIDKey_array = array('B', UIDKey.decode("hex"))
	
	# Start requesting random data from the MP
	print "Fetching random numbers..."
	rand_aes_key1 = array('B')
	rand_aes_key2 = array('B')
	rand_req_uid_key = array('B')
	set_mooltipass_password_random_payload = array('B')
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_RANDOM_NUMBER, 0, None))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	rand_aes_key1.extend(data[DATA_INDEX:DATA_INDEX+AES_KEY_SIZE])
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_RANDOM_NUMBER, 0, None))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	rand_aes_key2.extend(data[DATA_INDEX:DATA_INDEX+AES_KEY_SIZE])
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_RANDOM_NUMBER, 0, None))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	rand_req_uid_key.extend(data[DATA_INDEX:DATA_INDEX+UID_REQUEST_KEY_SIZE])
	set_mooltipass_password_random_payload.extend(rand_aes_key1)
	set_mooltipass_password_random_payload.extend(rand_aes_key2[0:30])
	rand_aes_key1_string = "".join(format(x, "02x") for x in rand_aes_key1)
	rand_aes_key2_string = "".join(format(x, "02x") for x in rand_aes_key2)
	print "Starting test, please make sure a card is inserted in reverse inside the mini!"
	
	# Set read timeouts
	mooltipass_device.getInternalDevice().setReadTimeout(3333)
	
	# Test - set UID
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_SET_UID, (UID_REQUEST_KEY_SIZE+UID_KEY_SIZE), [0]*(UID_REQUEST_KEY_SIZE+UID_KEY_SIZE)))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	if data == None or data[DATA_INDEX] != 0x01:
		print "OK - Couldn't set new UID"
	else:
		print "FAIL - Other UID set!"
		
	# Test - Get UID with erroneous req key
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_UID, UID_REQUEST_KEY_SIZE, rand_req_uid_key))
	data = mooltipass_device.getInternalDevice().receiveHidPacket()
	if data[LEN_INDEX] == 0x01:
		print "OK - Couln't fetch UID with random key"
	else:
		print "FAIL - Fetched UID with random key"
	
	# Test - Get UID with good req key
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_GET_UID, UID_REQUEST_KEY_SIZE, UIDReqKey_array))
	data = mooltipass_device.getInternalDevice().receiveHidPacket()
	if data[LEN_INDEX] == 0x01:
		print "FAIL - Couln't fetch UID"
	else:
		print "OK - Fetched UID"
		if data[DATA_INDEX:DATA_INDEX+6] == UIDKey_array:
			print "OK - UID fetched is correct!"
		else:
			print "FAIL - UID fetched is different than the one provided!"
			print data[DATA_INDEX:DATA_INDEX+6], "instead of", UIDKey_array
	
	# Test - Set New AES KEY 1 & KEY 2		
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_SET_BOOTLOADER_PWD, 62, set_mooltipass_password_random_payload))
	data = mooltipass_device.getInternalDevice().receiveHidPacketWithTimeout()
	if data == None or data[DATA_INDEX] != 0x01:
		print "OK - Couldn't set new Mooltipass password"
	else:
		print "FAIL - New Mooltipass password was set"
		
	# Set read timeouts
	mooltipass_device.getInternalDevice().setReadTimeout(130000)
		
	# Test bundle upload with wrong password
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, AESKey1, None, "updatefile.img", False)
	result = mooltipass_device.uploadBundle("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "updatefile.img", False)
	if result == False:
		print "OK - Couldn't start bundle upload with wrong password"
	else:
		print "FAIL - Could start bundle upload with wrong password"
	
	# Generate password for bundle upload
	text_password = generateBundlePasswordUpload(mooltipass_device.getMooltipassVersionAndVariant()[1], UIDKey_array, AESKey2_array)
		
	# Test nominal firmware update with good aes key and good password, no new key flag
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, AESKey1, None, "updatefile.img", False)
	print "Please accept prompt on the device"
	mooltipass_device.uploadBundle(text_password, "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "OK - Same firmware upload with good AES key 1 & AES key 2 - no new key flag"
	else:
		print "FAIL - Same firmware upload with good AES key 1 & AES key 2 - no new key flag"
	# Still AESKey1
	
	# Generate password for bundle upload
	text_password = generateBundlePasswordUpload(mooltipass_device.getMooltipassVersionAndVariant()[1], UIDKey_array, AESKey2_array)
		
	# Test nominal firmware update with good aes key and good password 
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, AESKey1, rand_aes_key1_string, "updatefile.img", False)
	print "Please accept prompt on the device"
	mooltipass_device.uploadBundle(text_password, "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "OK - Same firmware upload with good AES key 1 & AES key 2"
	else:
		print "FAIL - Same firmware upload with good AES key 1 & AES key 2"
	# Changed to rand_aes_key1_string
	
	# Generate password for bundle upload
	text_password = generateBundlePasswordUpload(mooltipass_device.getMooltipassVersionAndVariant()[1], UIDKey_array, AESKey2_array)
		
	# Test nominal firmware update with bad aes key and good password 
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, AESKey1, rand_aes_key1_string, "updatefile.img", False)
	print "Please accept prompt on the device"
	mooltipass_device.uploadBundle(text_password, "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	print "Don't forget to scroll a little to pass the tutorial, then wait a few seconds"
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "FAIL - Same firmware upload with bad AES key 1 & good AES key 2"
	else:
		print "OK - Same firmware upload with bad AES key 1 & good AES key 2"
	# Still rand_aes_key1_string
	
	# Generate password for bundle upload
	text_password = generateBundlePasswordUpload(mooltipass_device.getMooltipassVersionAndVariant()[1], UIDKey_array, AESKey2_array)
		
	# Test nominal firmware update with good aes key and good password 
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, new_firmware, rand_aes_key1_string, AESKey1, "updatefile.img", False)
	print "Please accept prompt on the device (click twice after a few seconds)"
	mooltipass_device.uploadBundle(text_password, "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "OK - Newer firmware upload with good AES key 1 & AES key 2"
	else:
		print "FAIL - Newer firmware upload with good AES key 1 & AES key 2"
	# Changed back to AESKey1
	
	# Generate password for bundle upload
	text_password = generateBundlePasswordUpload(mooltipass_device.getMooltipassVersionAndVariant()[1], UIDKey_array, AESKey2_array)
		
	# Test nominal firmware update with good aes key and good password but older firmware
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, old_firmware, AESKey1, AESKey1, "updatefile.img", False)
	print "Please accept prompt on the device"
	mooltipass_device.uploadBundle(text_password, "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	print "Don't forget to scroll a little to pass the tutorial, then wait a few seconds"
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "FAIL - Older firmware upload with good AES key 1 & AES key 2"
	else:
		print "OK - Older firmware upload with good AES key 1 & AES key 2"
	# Still AESKey1
		
	# Test nominal firmware update with good aes key and good password
	firmwareBundlePackAndSign.bundlePackAndSign(graphics_bundle, new_firmware, AESKey1, None, "updatefile.img", False)
	print "Please accept prompt on the device (click twice after a few seconds)"
	mooltipass_device.uploadBundle(text_password, "updatefile.img", False)
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	usr_answer = raw_input("Tutorial displayed? [y/n]: ")
	if usr_answer == "y":
		print "OK - Same firmware upload with good AES key 1 & AES key 2"
	else:
		print "FAIL - Same firmware upload with good AES key 1 & AES key 2"
	# Still AESKey1
	
	# Timeout test for media upload
	text_password = generateBundlePasswordUpload(mooltipass_device.getMooltipassVersionAndVariant()[1], UIDKey_array, AESKey2_array)
	password = array('B', text_password.decode("hex"))
	mooltipass_device.getInternalDevice().sendHidPacket(mpmSecGetPacketForCommand(CMD_IMPORT_MEDIA_START, MINI_DEVICE_PASSWORD_SIZE, password))
	print "Please accept prompt on the device (click twice after a few seconds)"
	print "Testing timeout... please wait 60 seconds"
	mpmSecWaitForDeviceDisconRecon(mooltipass_device)
	print "OK - Timeout Test"
	
	
Example #8
0
def main():
	skipConnection = False
	
	# If an arg is supplied and if the command doesn't require to connect to a device
	if len(sys.argv) > 1 and sys.argv[1] in nonConnectionCommands:
		skipConnection = True

	if not skipConnection:
		# HID device constructor
		mooltipass_device = mooltipass_hid_device()	
		
		# Connect to device
		if mooltipass_device.connect(True) == False:
			sys.exit(0)
			
		# Get Mooltipass Version
		version_data = mooltipass_device.getMooltipassVersionAndVariant()
		print "Mooltipass version: " + version_data[1] + ", variant: " + version_data[2] + ", " + str(version_data[0]) + "Mb of Flash"
			
		# Print Mooltipass status
		print "Mooltipass status:", mooltipass_device.getMooltipassStatus()
		print ""
	
	# See if args were passed
	if len(sys.argv) > 1:
		if sys.argv[1] == "uploadBundle":
			# extract args
			if len(sys.argv) > 2:
				filename = sys.argv[2]
			else:
				filename = None
			if len(sys.argv) > 3:
				password = sys.argv[3]
			else:
				password = None
			# start upload
			mooltipass_device.uploadBundle(password, filename, True)
			
		if sys.argv[1] == "packAndSign":
			if len(sys.argv) > 5:
				# Depending on number of args, set a new password or not
				if len(sys.argv) > 6:
					firmwareBundlePackAndSign.bundlePackAndSign(sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], sys.argv[6], True)
				else:
					firmwareBundlePackAndSign.bundlePackAndSign(sys.argv[2], sys.argv[3], sys.argv[4], None, sys.argv[5], True)					
			else:
				print "packAndSign: not enough args!"
				
		if sys.argv[1] == "packSignUpload":
			if len(sys.argv) > 5:
				# Depending on number of args, set a new password or not
				if len(sys.argv) > 6:
					bundle_gen = firmwareBundlePackAndSign.bundlePackAndSign(sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], "updatefile.img", True)
				else:
					bundle_gen = firmwareBundlePackAndSign.bundlePackAndSign(sys.argv[2], sys.argv[3], sys.argv[4], None, "updatefile.img", True)
				# Did we generate the bundle?
				if bundle_gen == True:
					if len(sys.argv) > 6:
						mooltipass_device.uploadBundle(sys.argv[6], "updatefile.img", True)
					else:
						mooltipass_device.uploadBundle(sys.argv[5], "updatefile.img", True)
			else:
				print "packAndSign: not enough args!"
				
		if sys.argv[1] == "minicheck":
			if len(sys.argv) > 3:
				mooltipass_security_check.mooltipassMiniSecCheck(mooltipass_device, sys.argv[2], sys.argv[3], sys.argv[4])
			else:
				print "minicheck: not enough args!"
		
		if sys.argv[1] == "init":
			if len(sys.argv) > 2:
				if version_data[2] == "mini":
					mooltipassMiniInit(mooltipass_device)
				else:
					print "Device Not Supported"
			else:
				print "init: not enough args!"
				
		if sys.argv[1] == "decrypt_mini_prod":
			if len(sys.argv) > 2:
				decryptMiniProdFile(sys.argv[2])		
			else:
				print "decrypt_mini_prod: not enough args!"
				
		if sys.argv[1] == "read_user_db_change_nb":
			mooltipass_device.getMooltipassUserDbChangeNumber()		
				
		if sys.argv[1] == "set_user_db_change_nb":
			if len(sys.argv) > 2:
				mooltipass_device.setMooltipassUserDbChangeNumber(int(sys.argv[2]))		
			else:
				print "set_user_db_change_nb: not enough args!"
				
		if sys.argv[1] == "get_free_user_slots":
			mooltipass_device.getFreeUserSlots()
			
		if sys.argv[1] == "change_login_description":
			mooltipass_device.changeLoginDescription()
			
		if sys.argv[1] == "add_credential":
			mooltipass_device.addCredential()
			
		if sys.argv[1] == "test_please_retry":
			mooltipass_device.testPleaseRetry()
			
		if sys.argv[1] == "get_card_cpz":
			mooltipass_device.getCardCpz()
			
		if sys.argv[1] == "lock":
			mooltipass_device.lock()