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>"
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()
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"
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()