def setUpModule(): """ This is run once for the full module, before all tests. It prepares some globals, including a single Primary ECU client instance. It also starts up an OEM Repository Server, Director Server, and Time Server. """ global primary_ecu_key global key_timeserver_pub global clock destroy_temp_dir() # Load the private key for this Primary ECU. key_pub = demo.import_public_key('primary') key_pri = demo.import_private_key('primary') primary_ecu_key = uptane.common.canonical_key_from_pub_and_pri( key_pub, key_pri) # Load the public timeserver key. key_timeserver_pub = demo.import_public_key('timeserver') # Generate a trusted initial time for the Primary. clock = tuf.formats.unix_timestamp_to_datetime(int(time.time())) clock = clock.isoformat() + 'Z' tuf.formats.ISO8601_DATETIME_SCHEMA.check_match(clock)
def setUpClass(cls): """ This is run once for the class, before all tests. Since there is only one class, this runs once. It prepares some variables and stores them in the class. """ destroy_temp_dir() # Create a directory for the Director's files. os.makedirs(TEST_DIRECTOR_DIR) # Load public and private keys for the Director into module dictionaries # to use in testing. for role in ['root', 'timestamp', 'snapshot']: keys_pri[role] = demo.import_private_key('director' + role) keys_pub[role] = demo.import_public_key('director' + role) # Because the demo's Director targets key is not named correctly.... # TODO: Remove this and add 'targets' back to the role list above when # the key is correctly renamed. keys_pub['targets'] = demo.import_public_key('director') keys_pri['targets'] = demo.import_private_key('director') # Load public keys for a Primary and some Secondaries and Primary, for use # in testing registration of ECUs and validation of manifests. for keyname in ['primary', 'secondary', 'secondary2']: keys_pub[keyname] = demo.import_public_key(keyname)
def create_vehicle(form): try: #print('\n\nCREATE_VEHICLE()') director = xmlrpc.client.ServerProxy('http://' + str(demo.DIRECTOR_SERVER_HOST) + ':' + str(demo.DIRECTOR_SERVER_PORT)) #print('\n\nAFTER CREATING DIRECTOR@ ADDR: {0}:{1}'.format(str(demo.DIRECTOR_SERVER_HOST), str(demo.DIRECTOR_SERVER_PORT))) # Add a new vehicle to the director repo (which includes writing to the repo) director.add_new_vehicle(form.vars.vin) director.write_director_repo(form.vars.vin) pri_ecu_key = demo.import_public_key('primary') sec_ecu_key = demo.import_public_key('secondary') ecu_pub_key = '' #print('\n\n\ncreating vehicle now\n{0}\ttype: {1}\n'.format(form.vars, type(form.vars))) #print('pri_ecu_key: {0}\nsec_ecu_key: {1}\necu_pub_key: {2}'.format(pri_ecu_key, sec_ecu_key, ecu_pub_key)) for e_id in form.vars.ecu_list: ecu = db(db.ecu_db.id == e_id).select().first() # Retrieve the filename to add the target to the director cwd = os.getcwd() filename = return_filename(ecu.update_image) filepath = cwd + str('/applications/UPTANE/test_uploads/' + filename) # Determine if ECU is primary or secondary is_primary = True if ecu.ecu_type == 'INFO' else False # If it's a secondary, then add the target to the director and write to the director repo if not is_primary: director.add_target_to_director( filepath, filename, form.vars.vin, ecu.ecu_type + str(form.vars.vin)) director.write_director_repo(form.vars.vin) # Register the ecu w/ the vehicle ecu_pub_key = pri_ecu_key if is_primary else sec_ecu_key #print('\necu.ecu_type: {0} + form.vars.vin: {1}\tis_primary: {2}'.format(ecu.ecu_type, form.vars.vin, is_primary)) # only register ecus ONCE - correct? director.register_ecu_serial(ecu.ecu_type + str(form.vars.vin), ecu_pub_key, form.vars.vin, is_primary) # Necessary? #director.write_director_repo(form.vars.vin) except Exception as e: print('Unable to create a new vehicle due to the following issue: {0}'. format(e))
def test_06_encode_and_validate_resigned_time_attestation(self): """ Test timeserver attestation encoding and decoding, with signing over DER ('re-sign' functionality in asn1_codec) and signature validation. """ signable_attestation = { str('signatures'): [{ str('keyid'): str('79c796d7e87389d1ebad04edce49faef611d139ee41ea9fb1931732afbfaac2e' ), str('sig'): str('a5ea6a3b685ad64f96c8c12145beda4efafddfac60bcdb45def35fe43c7d1150a182a1b50a1463bfffb0ef8d30b6203aa8b5365b0b7176312e1e9d7e355e550e' ), str('method'): str('ed25519') }], str('signed'): { str('nonces'): [1], str('time'): str('2017-03-08T17:09:56Z') } } # Load the timeserver's private key to sign a time attestation, and public # key to verify that signature. timeserver_key = demo.import_private_key('timeserver') timeserver_key_pub = demo.import_public_key('timeserver') tuf.formats.ANYKEY_SCHEMA.check_match(timeserver_key) tuf.formats.ANYKEY_SCHEMA.check_match(timeserver_key_pub) # First, calculate what we'll be verifying at the end of this test. # The re-signing in the previous line produces a signature over the SHA256 # hash of the DER encoding of the ASN.1 format of the 'signed' portion of # signable_attestation. We produce it here so that we can check it against # the result of encoding, resigning, and decoding. der_signed = asn1_codec.convert_signed_metadata_to_der( signable_attestation, only_signed=True) der_signed_hash = hashlib.sha256(der_signed).digest() # Now perform the actual conversion to ASN.1/DER of the full # signable_attestation, replacing the signature (which was given as # signatures over the Python 'signed' dictionary) with a signature over # the hash of the DER encoding of the 'signed' ASN.1 data. # This is the final product to be distributed back to a Primary client. der_attestation = asn1_codec.convert_signed_metadata_to_der( signable_attestation, private_key=timeserver_key, resign=True) # Now, in order to test the final product, decode it back from DER into # pyasn1 ASN.1, and convert back into Uptane's standard Python dictionary # form. pydict_again = asn1_codec.convert_signed_der_to_dersigned_json( der_attestation) # Check the extracted signature against the hash we produced earlier. self.assertTrue( tuf.keys.verify_signature(timeserver_key_pub, pydict_again['signatures'][0], der_signed_hash))
def setUpClass(cls): """ This is run once for the full class (and so the full module, which contains only one class), before all tests. It prepares some variables and stores them in the class. """ destroy_temp_dir() # Load the private key for this Secondary ECU. cls.secondary_ecu_key = uptane.common.canonical_key_from_pub_and_pri( demo.import_public_key('secondary'), demo.import_private_key('secondary')) # Load the public timeserver key. cls.key_timeserver_pub = demo.import_public_key('timeserver') cls.key_timeserver_pri = demo.import_private_key('timeserver') # Load the public director key. cls.key_directortargets_pub = demo.import_public_key('director') # Generate a trusted initial time for the Secondaries. cls.initial_time = tuf.formats.unix_timestamp_to_datetime( int(time.time())).isoformat() + 'Z' tuf.formats.ISO8601_DATETIME_SCHEMA.check_match(cls.initial_time) # Set up client directories for the two Secondaries, containing the # initial root.json and root.der (both, for good measure) metadata files # so that the clients can validate further metadata they obtain. # NOTE that running multiple clients in the same Python process does not # work normally in the reference implementation, as the value of # tuf.conf.repository_directories is client-specific, and it is set during # uptane.common.create_directory_structure_for_client, and used when a # client is created (initialization of a Secondary in our case) # We're going to cheat in this test module for the purpose of testing # and update tuf.conf.repository_directories before each Secondary is # created, to refer to the client we're creating. for client_dir in TEMP_CLIENT_DIRS: uptane.common.create_directory_structure_for_client( client_dir, TEST_PINNING_FNAME, { 'imagerepo': TEST_IMAGE_REPO_ROOT_FNAME, 'director': TEST_DIRECTOR_ROOT_FNAME })
def setUpClass(cls): """ This is run once for the class, before all tests. Since there is only one class, this runs once. It prepares some variables and stores them in the class. """ # Load a public and corresponding private key to use in testing. for key in ['secondary', 'primary', 'timeserver']: keys_pri[key] = demo.import_private_key(key) keys_pub[key] = demo.import_public_key(key) assert keys_pri[key]['keyid'] == keys_pub[key]['keyid'], 'Bad test data!'
def test_demo_timeserver(): """ Test the demo timeserver. # TODO: Consider moving these tests into a demo integration test module. """ I_TO_PRINT = TO_PRINT + uptane.YELLOW + '[test_demo_timeserver()]: ' + uptane.ENDCOLORS #TODO: Print to be deleted print(str('%s %s' % (I_TO_PRINT, 'Testing the Demo Timeserver'))) #TODO: Until here # Prepare to validate signatures. timeserver_key_pub = demo.import_public_key('timeserver') tuf.formats.ANYKEY_SCHEMA.check_match(timeserver_key_pub) # Fetch a normal signed time attestation, without ASN.1 format or DER # encoding, and validate the signature. signed_time = timeserver.get_signed_time([1, 2]) assert len( signed_time['signatures']) == 1, 'Unexpected number of signatures.' assert uptane.common.verify_signature_over_metadata( timeserver_key_pub, signed_time['signatures'][0], signed_time['signed'], DATATYPE_TIME_ATTESTATION, metadata_format='json' ), 'Demo Timeserver self-test fail: unable to verify signature over JSON.' # Fetch a DER-encoded converted-to-ASN.1 signed time attestation, with a # signature over the DER encoding. der_signed_time = timeserver.get_signed_time_der([2, 9, 151]) # Encapsulate that in a Binary object for XML-RPC. xb_der_signed_time = xmlrpc_client.Binary(der_signed_time) assert der_signed_time == xb_der_signed_time.data, \ 'Demo Timeserver self-test fail: xmlrpc Binary encapsulation issue' # Validate that signature. for pydict_again in [ asn1_codec.convert_signed_der_to_dersigned_json( der_signed_time, DATATYPE_TIME_ATTESTATION), asn1_codec.convert_signed_der_to_dersigned_json( xb_der_signed_time.data, DATATYPE_TIME_ATTESTATION) ]: assert uptane.common.verify_signature_over_metadata( timeserver_key_pub, pydict_again['signatures'][0], pydict_again['signed'], DATATYPE_TIME_ATTESTATION, metadata_format='der' ), 'Demo Timeserver self-test fail: unable to verify signature over DER'
def setUpClass(cls): """ This is run once for the class, before all tests. Since there is only one class, this runs once. It prepares some variables and stores them in the class. """ destroy_temp_dir() # Load the private key for this Primary ECU. cls.ecu_key = uptane.common.canonical_key_from_pub_and_pri( demo.import_public_key('primary'), demo.import_private_key('primary')) # Load the public timeserver key. cls.key_timeserver_pub = demo.import_public_key('timeserver') cls.key_timeserver_pri = demo.import_private_key('timeserver') # Generate a trusted initial time for the Primary. cls.initial_time = tuf.formats.unix_timestamp_to_datetime( int(time.time())).isoformat() + 'Z' tuf.formats.ISO8601_DATETIME_SCHEMA.check_match(cls.initial_time)
def load_or_generate_key(use_new_keys=False): """Load or generate an ECU's private key.""" global ecu_key if use_new_keys: demo.generate_key('secondary') # Load in from the generated files. key_pub = demo.import_public_key('secondary') key_pri = demo.import_private_key('secondary') ecu_key = uptane.common.canonical_key_from_pub_and_pri(key_pub, key_pri)
def test_set_timeserver_key(self): new_key_pub = demo.import_public_key('directorsnapshot') new_key = uptane.common.canonical_key_from_pub_and_pri( new_key_pub, demo.import_private_key('directorsnapshot')) tuf.formats.ANYKEY_SCHEMA.check_match(new_key) timeserver.set_timeserver_key(new_key) # Repeat two of the tests with the new key. t = self.test_get_signed_time() t_der = self.test_get_signed_time_der()
def load_or_generate_key(vin, use_new_keys=False): """Load or generate an ECU's private key.""" I_TO_PRINT = TO_PRINT + uptane.YELLOW + '[load_or_generate_key(use_new_keys)]: ' + uptane.ENDCOLORS #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'Loading or generating keys with use_new_keys:', use_new_keys))) #TODO: Until here global ecu_key if use_new_keys: demo.generate_key(str('%s%s' % (vin, '_keyPair_secondary'))) # Load in from the generated files. key_pub = demo.import_public_key(str('%s%s' % (vin, '_keyPair_secondary'))) key_pri = demo.import_private_key(str('%s%s' % (vin, '_keyPair_secondary'))) ecu_key = uptane.common.canonical_key_from_pub_and_pri(key_pub, key_pri)
def load_or_generate_key(use_new_keys=False): """Load or generate an ECU's private key.""" I_TO_PRINT = TO_PRINT + uptane.YELLOW + '[load_or_generate_key()]: ' + uptane.ENDCOLORS #TODO: Print to be deleted print( str('%s %s %s' % (I_TO_PRINT, 'Loading or generating keys with use_new_keys:', use_new_keys))) #TODO: Until here global ecu_key if use_new_keys: demo.generate_key('primary2') # Load in from the generated files. key_pub = demo.import_public_key('primary2') #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'primary_key_pub:', key_pub))) #TODO: Until here key_pri = demo.import_private_key('primary2') #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'primary_key_pri:', key_pri))) #TODO: Until here ecu_key = uptane.common.canonical_key_from_pub_and_pri(key_pub, key_pri) #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'ecu_key:', ecu_key))) #TODO: Until here #TODO: Print to be deleted print(str('%s %s' % (I_TO_PRINT, 'Returning...')))
def ATTACK_send_manifest_with_wrong_sig_to_primary(): """ Attack: MITM w/o key modifies ECU manifest and signs with a different ECU's key. """ # Discard the signatures and copy the signed contents of the most recent # signed ecu manifest. import copy corrupt_manifest = copy.copy(most_recent_signed_ecu_manifest['signed']) corrupt_manifest[ 'attacks_detected'] += 'Everything is great; PLEASE BELIEVE ME THIS TIME!' signable_corrupt_manifest = tuf.formats.make_signable(corrupt_manifest) uptane.formats.SIGNABLE_ECU_VERSION_MANIFEST_SCHEMA.check_match( signable_corrupt_manifest) # Attacker loads a key she may have (perhaps some other ECU's key) key2_pub = demo.import_public_key('secondary2') key2_pri = demo.import_private_key('secondary2') ecu2_key = uptane.common.canonical_key_from_pub_and_pri(key2_pub, key2_pri) keys = [ecu2_key] # Attacker signs the modified manifest with that other key. signed_corrupt_manifest = uptane.common.sign_signable( signable_corrupt_manifest, keys) uptane.formats.SIGNABLE_ECU_VERSION_MANIFEST_SCHEMA.check_match( signed_corrupt_manifest) #import xmlrpc.client # for xmlrpc.client.Fault try: submit_ecu_manifest_to_primary(signed_corrupt_manifest) except xmlrpc.client.Fault as e: print('Primary REJECTED the fraudulent ECU manifest.') else: print('Primary ACCEPTED the fraudulent ECU manifest!')
def clean_slate( use_new_keys=False, #client_directory_name=None, vin=_vin, ecu_serial=_ecu_serial, primary_host=None, primary_port=None): """ """ global secondary_ecu global _vin global _ecu_serial global _primary_host global _primary_port global nonce global CLIENT_DIRECTORY global attacks_detected _vin = vin _ecu_serial = ecu_serial if primary_host is not None: _primary_host = primary_host if primary_port is not None: _primary_port = primary_port CLIENT_DIRECTORY = os.path.join( uptane.WORKING_DIR, CLIENT_DIRECTORY_PREFIX + demo.get_random_string(5)) # Load the public timeserver key. key_timeserver_pub = demo.import_public_key('timeserver') # Set starting firmware fileinfo (that this ECU had coming from the factory) factory_firmware_fileinfo = { 'filepath': '/secondary_firmware.txt', 'fileinfo': { 'hashes': { 'sha512': '706c283972c5ae69864b199e1cdd9b4b8babc14f5a454d0fd4d3b35396a04ca0b40af731671b74020a738b5108a78deb032332c36d6ae9f31fae2f8a70f7e1ce', 'sha256': '6b9f987226610bfed08b824c93bf8b2f59521fce9a2adef80c495f363c1c9c44' }, 'length': 37 } } # Prepare this ECU's key. load_or_generate_key(use_new_keys) # Generate a trusted initial time for the Secondary. clock = tuf.formats.unix_timestamp_to_datetime(int(time.time())) clock = clock.isoformat() + 'Z' tuf.formats.ISO8601_DATETIME_SCHEMA.check_match(clock) # Create directory structure for the client and copy the root files from the # repositories. First, schedule the deletion of this directory to occur when # the script ends (so that it's deleted even if an error occurs here). atexit.register(clean_up_temp_folder) uptane.common.create_directory_structure_for_client( CLIENT_DIRECTORY, create_secondary_pinning_file(), { demo.IMAGE_REPO_NAME: demo.IMAGE_REPO_ROOT_FNAME, demo.DIRECTOR_REPO_NAME: os.path.join(demo.DIRECTOR_REPO_DIR, vin, 'metadata', 'root' + demo.METADATA_EXTENSION) }) # Configure tuf with the client's metadata directories (where it stores the # metadata it has collected from each repository, in subdirectories). tuf.conf.repository_directory = CLIENT_DIRECTORY # This setting should probably be called CLIENT_DIRECTORY instead, post-TAP4. # Initialize a full verification Secondary ECU. # This also generates a nonce to use in the next time query, sets the initial # firmware fileinfo, etc. secondary_ecu = secondary.Secondary( full_client_dir=CLIENT_DIRECTORY, director_repo_name=demo.DIRECTOR_REPO_NAME, vin=_vin, ecu_serial=_ecu_serial, ecu_key=ecu_key, time=clock, firmware_fileinfo=factory_firmware_fileinfo, timeserver_public_key=key_timeserver_pub) try: register_self_with_director() except xmlrpc_client.Fault: print( 'Registration with Director failed. Now assuming this Secondary is ' 'already registered.') try: register_self_with_primary() except xmlrpc_client.Fault: print( 'Registration with Primary failed. Now assuming this Secondary is ' 'already registered.') print('\n' + GREEN + ' Now simulating a Secondary that rolled off the ' 'assembly line\n and has never seen an update.' + ENDCOLORS) print("Generating this Secondary's first ECU Version Manifest and sending " "it to the Primary.") generate_signed_ecu_manifest() submit_ecu_manifest_to_primary()
def clean_slate(use_new_keys=False, additional_root_key=False, additional_targets_key=False): global repo global director_service_instance # ---------------- # REPOSITORY SETUP: # ---------------- # Create repo at './repodirector' repo = rt.create_new_repository(demo.DIRECTOR_REPO_NAME) # Create keys and/or load keys into memory. if use_new_keys: demo.generate_key('directorroot') demo.generate_key('directortimestamp') demo.generate_key('directorsnapshot') demo.generate_key('director') # targets if additional_root_key: demo.generate_key('directorroot2') if additional_targets_key: demo.generate_key('director2') key_dirroot_pub = demo.import_public_key('directorroot') key_dirroot_pri = demo.import_private_key('directorroot') key_dirtime_pub = demo.import_public_key('directortimestamp') key_dirtime_pri = demo.import_private_key('directortimestamp') key_dirsnap_pub = demo.import_public_key('directorsnapshot') key_dirsnap_pri = demo.import_private_key('directorsnapshot') key_dirtarg_pub = demo.import_public_key('director') key_dirtarg_pri = demo.import_private_key('director') key_dirroot2_pub = None key_dirroot2_pri = None if additional_root_key: key_dirroot2_pub = demo.import_public_key('directorroot2') key_dirroot2_pri = demo.import_private_key('directorroot2') if additional_targets_key: key_dirtarg2_pub = demo.import_public_key('director2') key_dirtarg2_pri = demo.import_private_key('director2') # Add top level keys to the main repository. repo.root.add_verification_key(key_dirroot_pub) repo.timestamp.add_verification_key(key_dirtime_pub) repo.snapshot.add_verification_key(key_dirsnap_pub) repo.targets.add_verification_key(key_dirtarg_pub) repo.root.load_signing_key(key_dirroot_pri) repo.timestamp.load_signing_key(key_dirtime_pri) repo.snapshot.load_signing_key(key_dirsnap_pri) repo.targets.load_signing_key(key_dirtarg_pri) if additional_targets_key: repo.targets.add_verification_key(key_dirtarg2_pub) repo.targets.load_signing_key(key_dirtarg2_pri) if additional_root_key: repo.root.add_verification_key(key_dirroot2_pub) repo.root.load_signing_key(key_dirroot2_pri) # Add target to director. # FOR NOW, we symlink the targets files on the director. # In the future, we probably have to have the repository tools add a function # like targets.add_target_from_metadata that doesn't require an actual target # file to exist, but instead provides metadata on some hypothetical file that # the director may not physically hold. if os.path.exists( os.path.join(demo.DIRECTOR_REPO_TARGETS_DIR, 'infotainment_firmware.txt')): os.remove( os.path.join(demo.DIRECTOR_REPO_TARGETS_DIR, 'infotainment_firmware.txt')) os.symlink( os.path.join(demo.MAIN_REPO_TARGETS_DIR, 'infotainment_firmware.txt'), os.path.join(demo.DIRECTOR_REPO_TARGETS_DIR, 'infotainment_firmware.txt')) fobj = open( os.path.join(demo.DIRECTOR_REPO_TARGETS_DIR, 'additional_file.txt'), 'w') fobj.write('Contents of additional_file.txt') fobj.close() repo.targets.add_target(os.path.join(demo.DIRECTOR_REPO_TARGETS_DIR, 'infotainment_firmware.txt'), custom={"ecu-serial-number": "ecu11111"}) #repo.targets.add_target( # os.path.join(demo.DIRECTOR_REPO_TARGETS_DIR, 'additional_file.txt'), # custom={"ecu-serial-number": "ecu11111"}) # -------------- # SERVICES SETUP: # -------------- # Create the demo Director instance. director_service_instance = director.Director( key_root=key_dirroot_pri, key_timestamp=key_dirtime_pri, key_snapshot=key_dirsnap_pri, key_targets=key_dirtarg_pri, ecu_public_keys=dict()) # Start with a hard-coded key for a single ECU for now. test_ecu_public_key = demo.import_public_key('secondary') test_ecu_serial = 'ecu11111' director_service_instance.register_ecu_serial(test_ecu_serial, test_ecu_public_key)
def clean_slate( use_new_keys=False, # client_directory_name=None, vin=_vin, ecu_serial=_ecu_serial): """ """ I_TO_PRINT = TO_PRINT + uptane.YELLOW + '[clean_slate(use_new_keys, vin, ecu_serial)]: ' + uptane.ENDCOLORS #TODO: Print to be deleted print(str('%s %s' % (I_TO_PRINT, 'clean_slate()'))) #TODO: Until here global primary_ecu global CLIENT_DIRECTORY global _vin global _ecu_serial global listener_thread _vin = vin _ecu_serial = ecu_serial # if client_directory_name is not None: # CLIENT_DIRECTORY = client_directory_name # else: CLIENT_DIRECTORY = os.path.join( uptane.WORKING_DIR, CLIENT_DIRECTORY_PREFIX + demo.get_random_string(5)) # TODO: Print to be deleted print( str('%s %s %s' % (I_TO_PRINT, 'Creating client directory:', CLIENT_DIRECTORY))) # TODO: Until here # Load the public timeserver key. key_timeserver_pub = demo.import_public_key('timeserver') #TODO: Print to be deleted print( str('%s %s %s' % (I_TO_PRINT, 'key_timeserver_pub:', key_timeserver_pub))) #TODO: Until here #TODO: Print to be deleted print( str('%s %s' % (I_TO_PRINT, 'Generate a trusted initial time for the Primary'))) #TODO: Until here # Generate a trusted initial time for the Primary. clock = tuf.formats.unix_timestamp_to_datetime(int(time.time())) clock = clock.isoformat() + 'Z' tuf.formats.ISO8601_DATETIME_SCHEMA.check_match(clock) #TODO: Print to be deleted print( str('%s %s' % (I_TO_PRINT, 'Loading or generating the Private key for this Primary ECU'))) #TODO: Until here # Load the private key for this Primary ECU. load_or_generate_key(vin, use_new_keys) # TODO: Print to be deleted print( str('%s %s' % ( I_TO_PRINT, 'Craft the directory structure for the client directory. Schecules deletion for temporary files' ))) # TODO: Until here # Craft the directory structure for the client directory, including the # creation of repository metadata directories, current and previous, putting # the pinning.json file in place, etc. First, schedule the deletion of this # directory to occur when the script ends (so that it's deleted even if an # error occurs here). atexit.register(clean_up_temp_folder) try: uptane.common.create_directory_structure_for_client( CLIENT_DIRECTORY, create_primary_pinning_file(), { demo.IMAGE_REPO_NAME: demo.IMAGE_REPO_ROOT_FNAME, demo.DIRECTOR_REPO_NAME: os.path.join(demo.DIRECTOR_REPO_DIR, vin, 'metadata', 'root' + demo.METADATA_EXTENSION) }) atexit.register(clean_up_temp_folder) except IOError: raise Exception( RED + 'Unable to create Primary client directory ' 'structure. Does the Director Repo for the vehicle exist yet?' + ENDCOLORS) # Configure tuf with the client's metadata directories (where it stores the # metadata it has collected from each repository, in subdirectories). tuf.conf.repository_directory = CLIENT_DIRECTORY #TODO: Print to be deleted print( str('%s %s %s %s %s %s %s' % (I_TO_PRINT, 'Initializating Primary ECU full_client_dir:', os.path.join(uptane.WORKING_DIR, CLIENT_DIRECTORY), 'vin:', vin, 'ecu_serial:', ecu_serial))) #TODO: Until here # Initialize a Primary ECU, making a client directory and copying the root # file from the repositories. primary_ecu = primary.Primary(full_client_dir=os.path.join( uptane.WORKING_DIR, CLIENT_DIRECTORY), director_repo_name=demo.DIRECTOR_REPO_NAME, vin=_vin, ecu_serial=_ecu_serial, primary_key=ecu_key, time=clock, timeserver_public_key=key_timeserver_pub) #TODO: Print to be deleted print( str('%s %s %s' % (I_TO_PRINT, 'Primary_ecu dictionary:', primary_ecu.__dict__))) #TODO: Until here if listener_thread is None: # TODO: Print to be deleted print( str('%s %s' % (I_TO_PRINT, 'Creating listener_thread for Primary'))) # TODO: Until here listener_thread = threading.Thread(target=listen) listener_thread.setDaemon(True) listener_thread.start() print('\n' + GREEN + 'Primary is now listening for messages from ' + 'Secondaries.' + ENDCOLORS) try: register_self_with_director() except xmlrpc_client.Fault: print( 'Registration with Director failed. Now assuming this Primary is ' 'already registered.') print(GREEN + '\n Now simulating a Primary that rolled off the assembly line' '\n and has never seen an update.' + ENDCOLORS) print( "Generating this Primary's first Vehicle Version Manifest and sending " "it to the Director.") #TODO: Print to be deleted print( str('%s %s' % (I_TO_PRINT, 'Trying to generate signed vehicle manifest'))) #TODO: Until here generate_signed_vehicle_manifest() #TODO: Print to be deleted print( str('%s %s' % (I_TO_PRINT, 'Trying to submit vehicle manifest to director'))) #TODO: Until here submit_vehicle_manifest_to_director() #TODO: Print to be deleted print(str('%s %s' % (I_TO_PRINT, 'Returning...')))
def clean_slate(use_new_keys=False): global repo I_TO_PRINT = TO_PRINT + uptane.YELLOW + '[clean_slate()]: ' + ENDCOLORS _print = True #TODO: Print to be deleted if _print: print( str('%s %s %s' % (I_TO_PRINT, 'Cleaning slate with use_new_keys:', use_new_keys))) #TODO: Until here print(LOG_PREFIX + 'Initializing repository') # Create target files: file1.txt and infotainment_firmware.txt #TODO: Print to be deleted if _print: print(I_TO_PRINT + 'Target files: %s' % target_files.keys()) #TODO: Until here if os.path.exists(demo.IMAGE_REPO_TARGETS_DIR): #TODO: Print to be deleted if _print: print(I_TO_PRINT + 'Removing files: ' + demo.IMAGE_REPO_TARGETS_DIR) #TODO: Until here shutil.rmtree(demo.IMAGE_REPO_TARGETS_DIR) #TODO: Print to be deleted if _print: print(I_TO_PRINT + 'Creating directories: ' + demo.IMAGE_REPO_TARGETS_DIR) #TODO: Until here os.makedirs(demo.IMAGE_REPO_TARGETS_DIR) #TODO: Print to be deleted if _print: print(I_TO_PRINT + 'Writing content for: %s' % target_files.keys()) #TODO: Until here for target in target_files.keys(): #TODO: Print to be deleted if _print: print(I_TO_PRINT + 'Target --> %s' % target) #TODO: Until here fobj = open(os.path.join(demo.IMAGE_REPO_TARGETS_DIR, target), 'w') fobj.write(target_files[target]) fobj.close() # Create repo at './repomain' #TODO: Print to be deleted if _print: print(I_TO_PRINT + 'Creating new repository at: ' + demo.IMAGE_REPO_NAME) #TODO: Until here repo = rt.create_new_repository(demo.IMAGE_REPO_NAME) print(LOG_PREFIX + 'Loading all keys') # Create keys and/or load keys into memory. if use_new_keys: demo.generate_key('mainroot') demo.generate_key('maintimestamp') demo.generate_key('mainsnapshot') demo.generate_key('maintargets') demo.generate_key('mainrole1') #TODO: Print to be deleted if _print: print( I_TO_PRINT + 'Loading keys for TOP-LEVEL roles: root, timestamp, snapshots, targets, role1' ) #TODO: Until here key_root_pub = demo.import_public_key('mainroot') #TODO: Print to be deleted if _print: print(str('%s %s %s' % (I_TO_PRINT, 'key_root_pub:', key_root_pub))) #TODO: Until here key_root_pri = demo.import_private_key('mainroot') #TODO: Print to be deleted if _print: print(str('%s %s %s' % (I_TO_PRINT, 'key_root_pri:', key_root_pri))) #TODO: Until here key_timestamp_pub = demo.import_public_key('maintimestamp') #TODO: Print to be deleted if _print: print( str('%s %s %s' % (I_TO_PRINT, 'key_timestamp_pub:', key_timestamp_pub))) #TODO: Until here key_timestamp_pri = demo.import_private_key('maintimestamp') #TODO: Print to be deleted if _print: print( str('%s %s %s' % (I_TO_PRINT, 'key_timestamp_pri:', key_timestamp_pri))) #TODO: Until here key_snapshot_pub = demo.import_public_key('mainsnapshot') #TODO: Print to be deleted if _print: print( str('%s %s %s' % (I_TO_PRINT, 'key_snapshot_pub:', key_snapshot_pub))) #TODO: Until here key_snapshot_pri = demo.import_private_key('mainsnapshot') #TODO: Print to be deleted if _print: print( str('%s %s %s' % (I_TO_PRINT, 'key_snapshot_pri:', key_snapshot_pri))) #TODO: Until here key_targets_pub = demo.import_public_key('maintargets') #TODO: Print to be deleted if _print: print( str('%s %s %s' % (I_TO_PRINT, 'key_targets_pub:', key_targets_pub))) #TODO: Until here key_targets_pri = demo.import_private_key('maintargets') #TODO: Print to be deleted if _print: print( str('%s %s %s' % (I_TO_PRINT, 'key_targets_pri:', key_targets_pri))) #TODO: Until here key_role1_pub = demo.import_public_key('mainrole1') #TODO: Print to be deleted if _print: print(str('%s %s %s' % (I_TO_PRINT, 'key_role1_pub:', key_role1_pub))) #TODO: Until here key_role1_pri = demo.import_private_key('mainrole1') #TODO: Print to be deleted if _print: print(str('%s %s %s' % (I_TO_PRINT, 'key_role1_pri:', key_role1_pri))) #TODO: Until here #TODO: Print to be deleted if _print: print( str('\n%s %s' % (I_TO_PRINT, 'Adding TOP-LEVEL keys to the main repository'))) #TODO: Until here # Add top level keys to the main repository. #TODO: Print to be deleted if _print: print(str('%s %s' % (I_TO_PRINT, 'Adding verification key_root_pub'))) #TODO: Until here repo.root.add_verification_key(key_root_pub) #TODO: Print to be deleted if _print: print( str('%s %s' % (I_TO_PRINT, 'Adding verification key_timestamp_pub'))) #TODO: Until here repo.timestamp.add_verification_key(key_timestamp_pub) #TODO: Print to be deleted if _print: print( str('%s %s' % (I_TO_PRINT, 'Adding verification key_snapshot_pub'))) #TODO: Until here repo.snapshot.add_verification_key(key_snapshot_pub) #TODO: Print to be deleted if _print: print( str('%s %s' % (I_TO_PRINT, 'Adding verification key_targets_pub'))) #TODO: Until here repo.targets.add_verification_key(key_targets_pub) #TODO: Print to be deleted if _print: print(str('%s %s' % (I_TO_PRINT, 'Adding signing key_root_pri'))) #TODO: Until here repo.root.load_signing_key(key_root_pri) #TODO: Print to be deleted if _print: print(str('%s %s' % (I_TO_PRINT, 'Adding signing key_timestamp_pri'))) #TODO: Until here repo.timestamp.load_signing_key(key_timestamp_pri) #TODO: Print to be deleted if _print: print(str('%s %s' % (I_TO_PRINT, 'Adding signing key_snapshot_pri'))) #TODO: Until here repo.snapshot.load_signing_key(key_snapshot_pri) #TODO: Print to be deleted if _print: print(str('%s %s' % (I_TO_PRINT, 'Adding signing key_targets_pri'))) #TODO: Until here repo.targets.load_signing_key(key_targets_pri) # Perform delegation from Image Repo's targets role to Image Repo's role1 # role. # TODO: <~> Re-enable delegations below. Currently, ASN1 conversion fails # when there are delegations. This is, of course, untenable, but for now, it # is more important to experiment with ASN1 than to have a sample delegation. # Delegate to a new Supplier. # repo.targets.delegate('role1', [key_role1_pub], # [os.path.join(demo.IMAGE_REPO_NAME, 'targets/file1.txt'), # os.path.join(demo.IMAGE_REPO_NAME, 'targets/infotainment_firmware.txt')], # threshold=1, backtrack=True, # restricted_paths=[os.path.join(demo.IMAGE_REPO_TARGETS_DIR, '*')]) # Add delegated role keys to repo # repo.targets('role1').load_signing_key(key_role1_pri) #TODO: Print to be deleted if _print: print(I_TO_PRINT + 'Adding some already created targets to imagerepo') #TODO: Until here # Add some starting image files, primarily for use with the web frontend. # add_target_to_imagerepo('demo/images/CommonINFO1.0.txt', 'CommonINFO1.0.txt') add_target_to_imagerepo('demo/images/infotainment_firmware.txt', 'infotainment_firmware.txt') add_target_to_imagerepo('demo/images/URV1.0.txt', 'URV1.0.txt') add_target_to_imagerepo('demo/images/URV1.1.txt', 'URV1.1.txt') add_target_to_imagerepo('demo/images/URV1.2.txt', 'URV1.2.txt') add_target_to_imagerepo('demo/images/UOC1.0.txt', 'UOC1.0.txt') add_target_to_imagerepo('demo/images/UOC1.1.txt', 'UOC1.1.txt') add_target_to_imagerepo('demo/images/UOC1.2.txt', 'UOC1.2.txt') add_target_to_imagerepo('demo/images/UOCMod1_new_firmware.img', 'UOCMod1_new_firmware.img') print(LOG_PREFIX + 'Signing and hosting initial repository metadata') write_to_live() host() listen()
def clean_slate(use_new_keys=False): global repo # Create target files: file1.txt and infotainment_firmware.txt if os.path.exists(demo.MAIN_REPO_TARGETS_DIR): shutil.rmtree(demo.MAIN_REPO_TARGETS_DIR) os.makedirs(demo.MAIN_REPO_TARGETS_DIR) fobj = open(os.path.join(demo.MAIN_REPO_TARGETS_DIR, 'file1.txt'), 'w') fobj.write('Contents of file1.txt') fobj.close() fobj = open( os.path.join(demo.MAIN_REPO_TARGETS_DIR, 'infotainment_firmware.txt'), 'w') fobj.write('Contents of infotainment_firmware.txt') fobj.close() # Create repo at './repomain' repo = rt.create_new_repository(demo.MAIN_REPO_NAME) # Create keys and/or load keys into memory. if use_new_keys: demo.generate_key('mainroot') demo.generate_key('maintimestamp') demo.generate_key('mainsnapshot') demo.generate_key('maintargets') demo.generate_key('mainrole1') key_root_pub = demo.import_public_key('mainroot') key_root_pri = demo.import_private_key('mainroot') key_timestamp_pub = demo.import_public_key('maintimestamp') key_timestamp_pri = demo.import_private_key('maintimestamp') key_snapshot_pub = demo.import_public_key('mainsnapshot') key_snapshot_pri = demo.import_private_key('mainsnapshot') key_targets_pub = demo.import_public_key('maintargets') key_targets_pri = demo.import_private_key('maintargets') key_role1_pub = demo.import_public_key('mainrole1') key_role1_pri = demo.import_private_key('mainrole1') # Add top level keys to the main repository. repo.root.add_verification_key(key_root_pub) repo.timestamp.add_verification_key(key_timestamp_pub) repo.snapshot.add_verification_key(key_snapshot_pub) repo.targets.add_verification_key(key_targets_pub) repo.root.load_signing_key(key_root_pri) repo.timestamp.load_signing_key(key_timestamp_pri) repo.snapshot.load_signing_key(key_snapshot_pri) repo.targets.load_signing_key(key_targets_pri) # Perform delegation from mainrepo's targets role to mainrepo's role1 role. # Delegate to a new Supplier. repo.targets.delegate('role1', [key_role1_pub], [ os.path.join(demo.MAIN_REPO_NAME, 'targets/file1.txt'), os.path.join(demo.MAIN_REPO_NAME, 'targets/infotainment_firmware.txt') ], threshold=1, backtrack=True, restricted_paths=[ os.path.join(demo.MAIN_REPO_TARGETS_DIR, '*') ]) # Add delegated role keys to repo repo.targets('role1').load_signing_key(key_role1_pri)
def clean_slate(use_new_keys=False): global director_service_instance I_TO_PRINT = TO_PRINT + uptane.YELLOW + '[clean_slate(use_new_keys)]: ' + ENDCOLORS #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'cleaning slate with use_new_keys:', use_new_keys))) #TODO: Until here director_dir = os.path.join(uptane.WORKING_DIR, 'director') #TODO: Print to be deleted print(str('%s %s %s %s' % (I_TO_PRINT, 'Adding: ', director_dir, 'to os.path'))) #TODO: Until here # Create a directory for the Director's files. if os.path.exists(director_dir): shutil.rmtree(director_dir) os.makedirs(director_dir) # Create keys and/or load keys into memory. print(LOG_PREFIX + 'Loading all keys') #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'Create keys and/or load keys into memory.\n\t\t[use_new_keys]:', use_new_keys))) #TODO: Until here #TODO: Print to be deleted #TODO: Force the creation of new keys #use_new_keys = True #print(str('%s %s %s %s' % ('\n\n\n', I_TO_PRINT, 'Forcing the creation of new keys by setting use_new_keys:', use_new_keys))) #TODO: Until here if use_new_keys: demo.generate_key('directorroot') demo.generate_key('directortimestamp') demo.generate_key('directorsnapshot') demo.generate_key('director') # targets key_dirroot_pub = demo.import_public_key('directorroot') #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'imported [key_dirroot_pub]:', key_dirroot_pub))) #TODO: Until here key_dirroot_pri = demo.import_private_key('directorroot') #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'imported [key_dirroot_pri]:', key_dirroot_pri))) #TODO: Until here key_dirtime_pub = demo.import_public_key('directortimestamp') #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'imported [key_dirtime_pub]:', key_dirtime_pub))) #TODO: Until here key_dirtime_pri = demo.import_private_key('directortimestamp') #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'imported [key_dirtime_pri]:', key_dirtime_pri))) #TODO: Until here key_dirsnap_pub = demo.import_public_key('directorsnapshot') #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'imported [key_dirsnap_pub]:', key_dirsnap_pub))) #TODO: Until here key_dirsnap_pri = demo.import_private_key('directorsnapshot') #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'imported [key_dirsnap_pri]:', key_dirsnap_pri))) #TODO: Until here key_dirtarg_pub = demo.import_public_key('director') #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'imported [key_dirtarg_pub]:', key_dirtarg_pub))) #TODO: Until here key_dirtarg_pri = demo.import_private_key('director') #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'imported [key_dirtarg_pri]:', key_dirtarg_pri))) #TODO: Until here print(LOG_PREFIX + 'Initializing vehicle repositories') #TODO: Print to be deleted print(str('%s %s' % (I_TO_PRINT, 'Creating demo Director instance'))) #TODO: Until here # Create the demo Director instance. director_service_instance = director.Director( director_repos_dir=director_dir, key_root_pri=key_dirroot_pri, key_root_pub=key_dirroot_pub, key_timestamp_pri=key_dirtime_pri, key_timestamp_pub=key_dirtime_pub, key_snapshot_pri=key_dirsnap_pri, key_snapshot_pub=key_dirsnap_pub, key_targets_pri=key_dirtarg_pri, key_targets_pub=key_dirtarg_pub) for vin in KNOWN_VINS.keys(): #TODO: Print to be deleted print(str('%s %s %s' % (I_TO_PRINT, 'Adding new vehicle to director instance with vin: ', vin))) #TODO: Until here # Create VIN instance in Director's server director_service_instance.add_new_vehicle(vin) # Generate key pair for this new VIN #demo.generate_key(str(vin + '_keyPair')) # Import its public key test_ecu_public_key = demo.import_public_key(str(vin + '_keyPair')) # Get ECU's serial test_ecu_serial = KNOWN_VINS[vin] # Register ECU Serial director_service_instance.register_ecu_serial(test_ecu_serial, test_ecu_public_key, vin=vin) # Vincular fitxer infotainment_firmware.txt for vin in inventory.ecus_by_vin: for ecu in inventory.ecus_by_vin[vin]: add_target_to_director(os.path.join(demo.IMAGE_REPO_TARGETS_DIR, 'infotainment_firmware.txt'), 'infotainment_firmware.txt', vin, ecu) # You can tell the Director about ECUs this way: # test_ecu_public_key = demo.import_public_key('secondary') # test_ecu_serial = 'ecu11111' # director_service_instance.register_ecu_serial( # test_ecu_serial, test_ecu_public_key, vin='111') #TODO: Print to be deleted #print(I_TO_PRINT + 'Adding first files') #TODO: Until here # Add a first target file, for use by every ECU in every vehicle in that the # Director starts off with. (Currently 3) # This copies the file to each vehicle repository's targets directory from # the Image Repository. # for vin in inventory.ecus_by_vin: # for ecu in inventory.ecus_by_vin[vin]: # add_target_to_director( # os.path.join(demo.IMAGE_REPO_TARGETS_DIR, 'infotainment_firmware.txt'), # 'infotainment_firmware.txt', # vin, # ecu) print(LOG_PREFIX + 'Signing and hosting initial repository metadata') write_to_live() host() listen()
def revoke_compromised_keys(): """ <Purpose> Revoke the current Timestamp, Snapshot, and Targets keys, and add a new keys for each role. This is a high-level version of the common function to update a role key. <Arguments> None. <Exceptions> None. <Side Effecs> None. <Returns> None. """ global repo # Pick names for the new Targets, Snapshot, and Timestamp keys. These will be # the files created. We do this instead of overwriting the existing files # because we want to be able to start over later with the same original state. new_targets_keyname = 'new_maintargets' new_timestamp_keyname = 'new_maintimestamp' new_snapshot_keyname = 'new_mainsnapshot' # Grab the old public keys. old_targets_public_key = demo.import_public_key('maintargets') old_timestamp_public_key = demo.import_public_key('maintimestamp') old_snapshot_public_key = demo.import_public_key('mainsnapshot') # Disassociate the old public keys from the roles. repo.targets.remove_verification_key(old_targets_public_key) repo.timestamp.remove_verification_key(old_timestamp_public_key) repo.snapshot.remove_verification_key(old_snapshot_public_key) # Generate new public and private keys and import them. demo.generate_key(new_targets_keyname) new_targets_public_key = demo.import_public_key(new_targets_keyname) new_targets_private_key = demo.import_private_key(new_targets_keyname) demo.generate_key(new_timestamp_keyname) new_timestamp_public_key = demo.import_public_key(new_timestamp_keyname) new_timestamp_private_key = demo.import_private_key(new_timestamp_keyname) demo.generate_key(new_snapshot_keyname) new_snapshot_public_key = demo.import_public_key(new_snapshot_keyname) new_snapshot_private_key = demo.import_private_key(new_snapshot_keyname) # Associate the new public keys with the roles. repo.targets.add_verification_key(new_targets_public_key) repo.timestamp.add_verification_key(new_timestamp_public_key) repo.snapshot.add_verification_key(new_snapshot_public_key) # Load the new signing keys to write metadata. The root key is unchanged, # and in the demo it is already loaded. Since we only need the keyid, # public keys can be used here. repo.targets.unload_signing_key(old_targets_public_key) repo.snapshot.unload_signing_key(old_snapshot_public_key) repo.timestamp.unload_signing_key(old_timestamp_public_key) # Make sure that the root metadata is written on the next repository write, # in addition to the other metadata. This should probably happen # automatically. # TODO: After the TUF fork merges, see if root is automatically marked dirty # when the signing keys for top-level roles are reassigned. repo.mark_dirty(['root']) repo.targets.load_signing_key(new_targets_private_key) repo.snapshot.load_signing_key(new_snapshot_private_key) repo.timestamp.load_signing_key(new_timestamp_private_key) # Write all the metadata changes to disk (metadata.staged) and copy them to # the hosted metadata directory. write_to_live()
def clean_slate(use_new_keys=False, client_directory_name=_client_directory_name, vin=_vin, ecu_serial=_ecu_serial): """ """ global secondary_ecu global _client_directory_name global _vin global _ecu_serial global nonce global listener_thread _client_directory_name = client_directory_name _vin = vin _ecu_serial = ecu_serial # Load the public timeserver key. key_timeserver_pub = demo.import_public_key('timeserver') # Set starting firmware fileinfo (that this ECU had coming from the factory) factory_firmware_fileinfo = { 'filepath': '/secondary_firmware.txt', 'fileinfo': { 'hashes': { 'sha512': '706c283972c5ae69864b199e1cdd9b4b8babc14f5a454d0fd4d3b35396a04ca0b40af731671b74020a738b5108a78deb032332c36d6ae9f31fae2f8a70f7e1ce', 'sha256': '6b9f987226610bfed08b824c93bf8b2f59521fce9a2adef80c495f363c1c9c44' }, 'length': 37 } } # Prepare this ECU's key. load_or_generate_key(use_new_keys) # Generate a trusted initial time for the Secondary. clock = tuf.formats.unix_timestamp_to_datetime(int(time.time())) clock = clock.isoformat() + 'Z' tuf.formats.ISO8601_DATETIME_SCHEMA.check_match(clock) # Initialize a full verification Secondary ECU, making a client directory and # copying the root file from the repositories. # This also generates a nonce to use in the next time query, sets the initial # firmware fileinfo, etc. secondary_ecu = secondary.Secondary( full_client_dir=os.path.join(uptane.WORKING_DIR, _client_directory_name), pinning_filename=demo.DEMO_PINNING_FNAME, vin=_vin, ecu_serial=_ecu_serial, fname_root_from_mainrepo=demo.MAIN_REPO_ROOT_FNAME, fname_root_from_directorrepo=demo.DIRECTOR_REPO_ROOT_FNAME, ecu_key=ecu_key, time=clock, firmware_fileinfo=factory_firmware_fileinfo, timeserver_public_key=key_timeserver_pub) # secondary_ecu.update_time_from_timeserver(nonce) register_self_with_primary() register_self_with_director() print('\n' + GREEN + ' Now simulating a Secondary that rolled off the ' 'assembly line\n and has never seen an update.' + ENDCOLORS)
def clean_slate(use_new_keys=False): global repo print(LOG_PREFIX + 'Initializing repository') # Create target files: file1.txt and infotainment_firmware.txt if os.path.exists(demo.IMAGE_REPO_TARGETS_DIR): shutil.rmtree(demo.IMAGE_REPO_TARGETS_DIR) os.makedirs(demo.IMAGE_REPO_TARGETS_DIR) fobj = open(os.path.join(demo.IMAGE_REPO_TARGETS_DIR, 'file1.txt'), 'w') fobj.write('Contents of file1.txt') fobj.close() fobj = open(os.path.join(demo.IMAGE_REPO_TARGETS_DIR, 'infotainment_firmware.txt'), 'w') fobj.write('Contents of infotainment_firmware.txt') fobj.close() # Create repo at './repomain' repo = rt.create_new_repository(demo.IMAGE_REPO_NAME) print(LOG_PREFIX + 'Loading all keys') # Create keys and/or load keys into memory. if use_new_keys: demo.generate_key('mainroot') demo.generate_key('maintimestamp') demo.generate_key('mainsnapshot') demo.generate_key('maintargets') demo.generate_key('mainrole1') key_root_pub = demo.import_public_key('mainroot') key_root_pri = demo.import_private_key('mainroot') key_timestamp_pub = demo.import_public_key('maintimestamp') key_timestamp_pri = demo.import_private_key('maintimestamp') key_snapshot_pub = demo.import_public_key('mainsnapshot') key_snapshot_pri = demo.import_private_key('mainsnapshot') key_targets_pub = demo.import_public_key('maintargets') key_targets_pri = demo.import_private_key('maintargets') key_role1_pub = demo.import_public_key('mainrole1') key_role1_pri = demo.import_private_key('mainrole1') # Add top level keys to the main repository. repo.root.add_verification_key(key_root_pub) repo.timestamp.add_verification_key(key_timestamp_pub) repo.snapshot.add_verification_key(key_snapshot_pub) repo.targets.add_verification_key(key_targets_pub) repo.root.load_signing_key(key_root_pri) repo.timestamp.load_signing_key(key_timestamp_pri) repo.snapshot.load_signing_key(key_snapshot_pri) repo.targets.load_signing_key(key_targets_pri) # Perform delegation from Image Repo's targets role to Image Repo's role1 # role. # TODO: <~> Re-enable delegations below. Currently, ASN1 conversion fails # when there are delegations. This is, of course, untenable, but for now, it # is more important to experiment with ASN1 than to have a sample delegation. # Delegate to a new Supplier. # repo.targets.delegate('role1', [key_role1_pub], # [os.path.join(demo.IMAGE_REPO_NAME, 'targets/file1.txt'), # os.path.join(demo.IMAGE_REPO_NAME, 'targets/infotainment_firmware.txt')], # threshold=1, backtrack=True, # restricted_paths=[os.path.join(demo.IMAGE_REPO_TARGETS_DIR, '*')]) # Add delegated role keys to repo # repo.targets('role1').load_signing_key(key_role1_pri) # Add some starting image files, primarily for use with the web frontend. add_target_to_imagerepo('demo/images/INFO1.0.txt', 'INFO1.0.txt') add_target_to_imagerepo('demo/images/TCU1.0.txt', 'TCU1.0.txt') add_target_to_imagerepo('demo/images/TCU1.1.txt', 'TCU1.1.txt') add_target_to_imagerepo('demo/images/TCU1.2.txt', 'TCU1.2.txt') add_target_to_imagerepo('demo/images/BCU1.0.txt', 'BCU1.0.txt') add_target_to_imagerepo('demo/images/BCU1.1.txt', 'BCU1.1.txt') add_target_to_imagerepo('demo/images/BCU1.2.txt', 'BCU1.2.txt') print(LOG_PREFIX + 'Signing and hosting initial repository metadata') write_to_live() host() listen()
def selected_ecus(selected_ecus): #print('inside selected ecus') ecu_id_list = request.vars['ecu_id_list'] changed_ecu_list = [] vehicle_id = request.vars['vehicle_id'] is_primary = False for ecu in selected_ecus: if str(ecu) not in ecu_id_list: changed_ecu_list.append(ecu) else: print(str(ecu) + ' is in the list!') #print('changed_ecu_list: {0}'.format(changed_ecu_list)) if changed_ecu_list: db.vehicle_db(db.vehicle_db.id == vehicle_id).update_record( ecu_list=selected_ecus) #if len(changed_ecu_list) == 1: # <~> Why use this condition? print('changed_ecu_list contains ' + repr(len(changed_ecu_list))) director = xmlrpc.client.ServerProxy('http://' + str(demo.DIRECTOR_SERVER_HOST) + ':' + str(demo.DIRECTOR_SERVER_PORT)) # <~> I'd expect vin to be the same within this call, since this # dialog is for an individual vehicle. No? vin = db(db.vehicle_db.id == vehicle_id).select().first().vin director.clear_vehicle_targets(vin) for i in range(len(changed_ecu_list)): cur_ecu = db(db.ecu_db.id == changed_ecu_list[i]).select().first() #print('\ncur_ecu: {0}'.format(cur_ecu)) # Do a check to see if it's the Primary (potentially add it after appending to # changed_ecu_list w/ boolean is_primary) is_primary = True if cur_ecu.ecu_type == 'INFO' else False #print('\ncur_ecu: {0}'.format(cur_ecu)) #print('\nis_primary: {0}'.format(is_primary)) # Add the bundle to the vehicle cwd = os.getcwd() #print('\ncwd now2: {0}'.format(cwd)) # Retrieve the filename filename = return_filename(cur_ecu.update_image) # <~> Why are we using test_uploads paths? We can't assume the # image files exist in the test_uploads folder. filepath = cwd + str('/applications/UPTANE/test_uploads/' + filename) vehicle_id = request.vars['vehicle_id'] #print('vehicle_id: {0}'.format(vehicle_id)) ecu_serial = cur_ecu.ecu_type + str(vin) #print('filepath: {0}\nfilename: {1}\nvin: {2}\necu_serial: {3}'.format(filepath, filename, vin, ecu_serial)) director.add_target_to_director(filepath, filename, vin, ecu_serial) director.write_director_repo(vin) pri_ecu_key = demo.import_public_key('primary') sec_ecu_key = demo.import_public_key('secondary') ecu_pub_key = '' # <~> Why would we register the ECU every time we want to update it? # (Am I missing something?) # # Register the ecu w/ the vehicle # is_primary = True if cur_ecu.ecu_type == 'INFO' else False # ecu_pub_key = pri_ecu_key if is_primary else sec_ecu_key # print('\necu.type+vin: {0}{1}\tform.vars.vin: {2}\tis_primary: {3}'.format(cur_ecu.ecu_type, str(vin), vin, is_primary)) # director.register_ecu_serial(cur_ecu.ecu_type+str(vin), ecu_pub_key, vin, is_primary) redirect( URL('index', vars=dict(ecu_id_list=ecu_id_list, selected_ecu_list=selected_ecus, changed_ecu_list=changed_ecu_list, vehicle_id=vehicle_id)))
def revoke_compromised_keys(): """ <Purpose> Revoke the current Timestamp, Snapshot, and Targets keys for all vehicles, and generate a new key for each role. This is a high-level version of the common function to update a role key. The director service instance is also updated with the key changes. <Arguments> None. <Exceptions> None. <Side Effecs> None. <Returns> None. """ I_TO_PRINT = TO_PRINT + uptane.YELLOW + '[revoke_compromised_keys()]: ' + ENDCOLORS #TODO: Print to be deleted print(str('%s %s' % (I_TO_PRINT, 'Revoke the current Timestamp, Snapshots, and Targets keys for all vehicles, and generate a new key for each role. This is a high-level version of the common function to update a role key. The director service instance is also updated with the key changes.'))) #TODO: Until here global director_service_instance # Generate news keys for the Targets, Snapshot, and Timestamp roles. Make # sure that the director service instance is updated to use the new keys. # The 'director' name actually references the targets role. # TODO: Change Director's targets key to 'directortargets' from 'director'. new_targets_keyname = 'new_director' new_timestamp_keyname = 'new_directortimestamp' new_snapshot_keyname = 'new_directorsnapshot' # References are needed for the old and new keys later below when we modify # the repository. Generate new keys for the Targets role... demo.generate_key(new_targets_keyname) new_targets_public_key = demo.import_public_key(new_targets_keyname) new_targets_private_key = demo.import_private_key(new_targets_keyname) old_targets_public_key = director_service_instance.key_dirtarg_pub # Timestamp... demo.generate_key(new_timestamp_keyname) new_timestamp_public_key = demo.import_public_key(new_timestamp_keyname) new_timestamp_private_key = demo.import_private_key(new_timestamp_keyname) old_timestamp_public_key = director_service_instance.key_dirtime_pub # And Snapshot. demo.generate_key(new_snapshot_keyname) new_snapshot_public_key = demo.import_public_key(new_snapshot_keyname) new_snapshot_private_key = demo.import_private_key(new_snapshot_keyname) old_snapshot_public_key = director_service_instance.key_dirsnap_pub # Set the new public and private Targets keys in the director service. # These keys are shared between all vehicle repositories. director_service_instance.key_dirtarg_pub = new_targets_public_key director_service_instance.key_dirtarg_pri = new_targets_private_key director_service_instance.key_dirtime_pub = new_timestamp_public_key director_service_instance.key_dirtime_pri = new_timestamp_private_key director_service_instance.key_dirsnap_pub = new_snapshot_public_key director_service_instance.key_dirsnap_pri = new_snapshot_private_key for vin in director_service_instance.vehicle_repositories: repository = director_service_instance.vehicle_repositories[vin] repo_dir = repository._repository_directory # Swap verification keys for the three roles. repository.targets.remove_verification_key(old_targets_public_key) repository.targets.add_verification_key(new_targets_public_key) repository.timestamp.remove_verification_key(old_timestamp_public_key) repository.timestamp.add_verification_key(new_timestamp_public_key) repository.snapshot.remove_verification_key(old_snapshot_public_key) repository.snapshot.add_verification_key(new_snapshot_public_key) # Unload the old signing keys so that the new metadata only contains # signatures produced by the new signing keys. Since this is based on # keyid, the public key can be used. repository.targets.unload_signing_key(old_targets_public_key) repository.snapshot.unload_signing_key(old_snapshot_public_key) repository.timestamp.unload_signing_key(old_timestamp_public_key) # Load the new signing keys to write metadata. The root key is unchanged, # and in the demo it is already loaded. repository.targets.load_signing_key(new_targets_private_key) repository.snapshot.load_signing_key(new_snapshot_private_key) repository.timestamp.load_signing_key(new_timestamp_private_key) # The root role is not automatically marked as dirty when the verification # keys are updated via repository.<non-root-role>.add_verification_key(). # TODO: Verify this behavior with the latest version of the TUF codebase. repository.mark_dirty(['root']) # Push the changes to "live". write_to_live()