Esempio n. 1
0
    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)
Esempio n. 2
0
def undo_sign_with_compromised_keys_attack(vin=None):
  """
  <Purpose>
    Undo the actions executed by sign_with_compromised_keys_attack().  Namely,
    move the valid metadata into the live and metadata.staged directories, and
    reload the valid keys for each repository.

  <Arguments>
    vin (optional)
      If not provided, all known vehicles will be reverted to normal state from
      attacked state. You may also provide a single VIN (string) indicating
      one vehicle to undo the attack for.

  <Side Effects>
    None.

  <Exceptions>
    None.

  <Returns>
    None.
  """
  # Re-load the valid keys, so that the repository objects can be updated to
  # reference them and replace the compromised keys set.
  valid_targets_private_key = demo.import_private_key('new_director')
  valid_timestamp_private_key = demo.import_private_key('new_directortimestamp')
  valid_snapshot_private_key = demo.import_private_key('new_directorsnapshot')

  current_targets_private_key = director_service_instance.key_dirtarg_pri
  current_timestamp_private_key = director_service_instance.key_dirtime_pri
  current_snapshot_private_key = director_service_instance.key_dirsnap_pri

  # Set the new private keys in the director service.  These keys are shared
  # between all vehicle repositories.
  director_service_instance.key_dirtarg_pri = valid_targets_private_key
  director_service_instance.key_dirtime_pri = valid_timestamp_private_key
  director_service_instance.key_dirsnap_pri = valid_snapshot_private_key

  # Revert to the last backup for all metadata in the Director repositories.
  restore_repositories(vin)

  if vin is None:
    vehicles_to_attack = director_service_instance.vehicle_repositories.keys()
  else:
    vehicles_to_attack = [vin]

  for vin in vehicles_to_attack:

    repository = director_service_instance.vehicle_repositories[vin]
    repo_dir = repository._repository_directory

    # Load the new signing keys to write metadata.
    repository.targets.load_signing_key(valid_targets_private_key)
    repository.snapshot.load_signing_key(valid_snapshot_private_key)
    repository.timestamp.load_signing_key(valid_timestamp_private_key)

  print(LOG_PREFIX + 'COMPLETED UNDO ATTACK')
Esempio n. 3
0
def reproduce_all_der_samples():

    pkey = demo.import_private_key('primary')
    skey = demo.import_private_key('secondary')
    skey2 = demo.import_private_key('maintimestamp')
    tkey = demo.import_private_key('timeserver')

    # Convert Timeserver Attestation sample
    derify_sample_time_attestation(
        '/Users/s/w/uptane/samples/sample_timeserver_attestation.json', tkey)

    # Convert ECU Manifest samples and test data
    samples_using_normal_key = [
        os.path.join(SAMPLE_DATA_DIR, 'sample_ecu_manifest.json'),
        os.path.join(SAMPLE_DATA_DIR, 'sample_ecu_manifest_TCUdemocar.json'),
        os.path.join(SAMPLE_DATA_DIR, 'sample_ecu_manifest_ecu11111.json'),
        os.path.join(FLAWED_MANIFEST_DIR, 'em2_unknown_ecu_manifest.json'),
        os.path.join(FLAWED_MANIFEST_DIR,
                     'em4_attack_detected_in_ecu_manifest.json')
    ]

    samples_using_wrong_key = [
        os.path.join(FLAWED_MANIFEST_DIR,
                     'em3_ecu_manifest_signed_with_wrong_key.json')
    ]

    for manifest in samples_using_normal_key:
        derify_sample_ecu_manifest(manifest, skey)

    for manifest in samples_using_wrong_key:
        derify_sample_ecu_manifest(manifest, skey2)

    # Convert Vehicle Manifest samples and test data

    samples_using_normal_key = [
        os.path.join(SAMPLE_DATA_DIR, 'sample_vehicle_manifest.json'),
        os.path.join(SAMPLE_DATA_DIR,
                     'sample_vehicle_version_manifest_democar.json'),
        os.path.join(FLAWED_MANIFEST_DIR, 'vm1_three_ecus_one_unknown.json'),
        os.path.join(FLAWED_MANIFEST_DIR,
                     'vm2_contains_one_unknown_ecu_manifest.json'),
        os.path.join(FLAWED_MANIFEST_DIR,
                     'vm4_attack_detected_in_ecu_manifest.json')
    ]

    samples_using_wrong_key = [
        os.path.join(FLAWED_MANIFEST_DIR,
                     'vm3_ecu_manifest_signed_with_wrong_key.json')
    ]

    for manifest in samples_using_normal_key:
        derify_sample_vehicle_manifest(manifest, skey, pkey)

    for manifest in samples_using_wrong_key:
        derify_sample_vehicle_manifest(manifest, skey2, pkey)
Esempio n. 4
0
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)
Esempio n. 5
0
def load_timeserver_key(use_new_keys=False):
    if use_new_keys:
        demo.generate_key('timeserver')
    # Load in from the generated files (whether new or old).
    timeserver_key = demo.import_private_key('timeserver')
    tuf.formats.ANYKEY_SCHEMA.check_match(timeserver_key)  # Is this redundant?

    return timeserver_key
Esempio n. 6
0
    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))
Esempio n. 7
0
    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
                })
Esempio n. 8
0
 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!'
Esempio n. 9
0
  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)
Esempio n. 10
0
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)
Esempio n. 11
0
    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()
Esempio n. 12
0
    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.
    """

        # Load the keys for the test Timeserver.
        # cls.key_timeserver_pub = demo.import_public_key('timeserver')
        # cls.key_timeserver_pri = demo.import_private_key('timeserver')
        cls.timeserver_key = demo.import_private_key('timeserver')

        tuf.formats.ANYKEY_SCHEMA.check_match(
            cls.timeserver_key)  # Is this redundant?

        timeserver.set_timeserver_key(cls.timeserver_key)
Esempio n. 13
0
def load_timeserver_key(use_new_keys=False):

    I_TO_PRINT = TO_PRINT + uptane.YELLOW + '[load_timeserver_key(use_new_keys)]: ' + uptane.ENDCOLORS
    #TODO: Print to be deleted
    print(
        str('%s %s %s' %
            (I_TO_PRINT, 'Loading timeserver key with use_new_keys:',
             use_new_keys)))
    #TODO: Until here

    if use_new_keys:
        demo.generate_key('timeserver')
    # Load in from the generated files (whether new or old).
    timeserver_key = demo.import_private_key('timeserver')
    tuf.formats.ANYKEY_SCHEMA.check_match(timeserver_key)  # Is this redundant?

    return timeserver_key
Esempio n. 14
0
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)
Esempio n. 15
0
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...')))
Esempio n. 16
0
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!')
Esempio n. 17
0
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()
Esempio n. 18
0
def restore_repositories(vin=None):
  """
  <Purpose>
    Restore the last backup of each Director repository.

    Metadata is copied from '{repo_dir}/metadata.backup' to
    '{repo_dir}/metadata.staged' and '{repo_dir}/metadata'

  <Arguments>
    vin (optional)
      If not provided, all known vehicle repositories will be restored to their
      backed-up state. You may also provide a single VIN (string) indicating
      one vehicle to restore from backup.

  <Exceptions>
    uptane.Error if backup does not exist

  <Side Effecs>
    None.

  <Returns>
    None.
  """

  I_TO_PRINT = TO_PRINT + uptane.YELLOW + '[restore_repositories(vin)]: ' + ENDCOLORS
  #TODO: Print to be deleted
  print(str('%s %s %s' % (I_TO_PRINT, 'Restoring repositories for vin:', vin)))
  #TODO: Until here

  if vin is None:
    repos_to_restore = director_service_instance.vehicle_repositories.keys()
  else:
    repos_to_restore = [vin]

  for vin in repos_to_restore:

    repo_dir = director_service_instance.vehicle_repositories[
        vin]._repository_directory

    # Copy the backup metadata to the metada.staged and live directories.  The
    # backup metadata should already exist if
    # sign_with_compromised_keys_attack() was called.

    if not os.path.exists(os.path.join(repo_dir, 'metadata.backup')):
      raise uptane.Error('Unable to restore backup of ' + repr(repo_dir) +
          '; no backup exists.')

    # Empty the existing (old) live metadata directory (relatively fast).
    print(LOG_PREFIX + 'Deleting ' + os.path.join(repo_dir, 'metadata.staged'))
    if os.path.exists(os.path.join(repo_dir, 'metadata.staged')):
      shutil.rmtree(os.path.join(repo_dir, 'metadata.staged'))

    # Atomically move the new metadata into place.
    print(LOG_PREFIX + 'Moving backup to ' +
        os.path.join(repo_dir, 'metadata.staged'))
    os.rename(os.path.join(repo_dir, 'metadata.backup'),
        os.path.join(repo_dir, 'metadata.staged'))

    # Re-load the repository from the restored metadata.stated directory.
    # (We're using a temp variable here, so we have to assign the new reference
    # to both the temp and the source variable.)
    print(LOG_PREFIX + 'Reloading repository from backup ' + repo_dir)
    director_service_instance.vehicle_repositories[vin] = rt.load_repository(
        repo_dir)

    # Load the new signing keys to write metadata. The root key is unchanged,
    # but must be reloaded because load_repository() was called.
    valid_root_private_key = demo.import_private_key('directorroot')
    director_service_instance.vehicle_repositories[vin].root.load_signing_key(
        valid_root_private_key)

    # Copy the staged metadata to a temp directory, which we'll move into place
    # atomically in a moment.
    shutil.copytree(os.path.join(repo_dir, 'metadata.staged'),
        os.path.join(repo_dir, 'metadata.livetemp'))

    # Empty the existing (old) live metadata directory (relatively fast).
    print(LOG_PREFIX + 'Deleting live hosted dir:' +
        os.path.join(repo_dir, 'metadata'))
    if os.path.exists(os.path.join(repo_dir, 'metadata')):
      shutil.rmtree(os.path.join(repo_dir, 'metadata'))

    # Atomically move the new metadata into place in the hosted directory.
    os.rename(os.path.join(repo_dir, 'metadata.livetemp'),
        os.path.join(repo_dir, 'metadata'))
    print(LOG_PREFIX + 'Repository ' + repo_dir + ' restored and hosted.')
Esempio n. 19
0
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()
Esempio n. 20
0
def sign_with_compromised_keys_attack(vin=None):
  """
  <Purpose>
    Re-generate Timestamp, Snapshot, and Targets metadata for all vehicles and
    sign each of these roles with its previously revoked key.  The default key
    names (director, directorsnapshot, directortimestamp, etc.) of the key
    files are used if prefix_of_previous_keys is None, otherwise
    'prefix_of_previous_keys' is prepended to them.  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>
    vin (optional)
      If not provided, all known vehicles will be attacked. You may also provide
      a single VIN (string) indicating one vehicle to attack.

  <Side Effects>
    None.

  <Exceptions>
    None.

  <Returns>
    None.
  """

  global director_service_instance

  print(LOG_PREFIX + 'ATTACK: arbitrary metadata, old key, all vehicles')

  # Start by backing up the repository before the attack occurs so that we
  # can restore it afterwards in undo_sign_with_compromised_keys_attack.
  backup_repositories(vin)

  # Load the now-revoked keys.
  old_targets_private_key = demo.import_private_key('director')
  old_timestamp_private_key = demo.import_private_key('directortimestamp')
  old_snapshot_private_key = demo.import_private_key('directorsnapshot')

  current_targets_private_key = director_service_instance.key_dirtarg_pri
  current_timestamp_private_key = director_service_instance.key_dirtime_pri
  current_snapshot_private_key = director_service_instance.key_dirsnap_pri

  # Ensure the director service uses the old (now-revoked) keys.
  director_service_instance.key_dirtarg_pri = old_targets_private_key
  director_service_instance.key_dirtime_pri = old_timestamp_private_key
  director_service_instance.key_dirsnap_pri = old_snapshot_private_key

  repo_dir = None

  if vin is None:
    vehicles_to_attack = director_service_instance.vehicle_repositories.keys()
  else:
    vehicles_to_attack = [vin]

  for vin in vehicles_to_attack:

    repository = director_service_instance.vehicle_repositories[vin]
    repo_dir = repository._repository_directory

    repository.targets.unload_signing_key(current_targets_private_key)
    repository.snapshot.unload_signing_key(current_snapshot_private_key)
    repository.timestamp.unload_signing_key(current_timestamp_private_key)

    # Load the old signing keys to generate the malicious metadata. The root
    # key is unchanged, and in the demo it is already loaded.
    repository.targets.load_signing_key(old_targets_private_key)
    repository.snapshot.load_signing_key(old_snapshot_private_key)
    repository.timestamp.load_signing_key(old_timestamp_private_key)

    repository.timestamp.version = repository.targets.version + 1
    repository.timestamp.version = repository.snapshot.version + 1
    repository.timestamp.version = repository.timestamp.version + 1

    # Metadata must be partially written, otherwise write() will throw
    # a UnsignedMetadata exception due to the invalid signing keys (i.e.,
    # we are using the old signing keys, which have since been revoked.
    repository.write(write_partial=True)

    # Copy the staged metadata to a temp directory we'll move into place
    # atomically in a moment.
    shutil.copytree(os.path.join(repo_dir, 'metadata.staged'),
        os.path.join(repo_dir, 'metadata.livetemp'))

    # Empty the existing (old) live metadata directory (relatively fast).
    if os.path.exists(os.path.join(repo_dir, 'metadata')):
      shutil.rmtree(os.path.join(repo_dir, 'metadata'))

    # Atomically move the new metadata into place.
    os.rename(os.path.join(repo_dir, 'metadata.livetemp'),
        os.path.join(repo_dir, 'metadata'))

  print(LOG_PREFIX + 'COMPLETED ATTACK')
Esempio n. 21
0
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()
Esempio n. 22
0
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()
Esempio n. 23
0
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)
Esempio n. 24
0
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)
Esempio n. 25
0
    def test_15_register_vehicle_manifest(self):

        manifest_json = {
            "signatures": [{
                "keyid":
                "9a406d99e362e7c93e7acfe1e4d6585221315be817f350c026bbee84ada260da",
                "method":
                "ed25519",
                "sig":
                "335272f77357dc0e9f1b74d72eb500e4ff0f443f824b83405e2b21264778d1610e0a5f2663b90eda8ab05a28b5b64fc15514020985d8a93576fe33b287e1380f"
            }],
            "signed": {
                "primary_ecu_serial": "INFOdemocar",
                "vin": "democar",
                "ecu_version_manifests": {
                    "TCUdemocar": [{
                        "signatures": [{
                            "keyid":
                            "49309f114b857e4b29bfbff1c1c75df59f154fbc45539b2eb30c8a867843b2cb",
                            "method":
                            "ed25519",
                            "sig":
                            "fd04c1edb0ddf1089f0d3fc1cd460af584e548b230d9c290deabfaf29ce5636b6b897eaa97feb64147ac2214c176bbb1d0fa8bb9c623011a0e48d258eb3f9108"
                        }],
                        "signed": {
                            "attacks_detected": "",
                            "ecu_serial": "TCUdemocar",
                            "previous_timeserver_time": "2017-05-18T16:37:46Z",
                            "timeserver_time": "2017-05-18T16:37:48Z",
                            "installed_image": {
                                "filepath": "/secondary_firmware.txt",
                                "fileinfo": {
                                    "length": 37,
                                    "hashes": {
                                        "sha256":
                                        "6b9f987226610bfed08b824c93bf8b2f59521fce9a2adef80c495f363c1c9c44",
                                        "sha512":
                                        "706c283972c5ae69864b199e1cdd9b4b8babc14f5a454d0fd4d3b35396a04ca0b40af731671b74020a738b5108a78deb032332c36d6ae9f31fae2f8a70f7e1ce"
                                    }
                                }
                            }
                        }
                    }]
                }
            }
        }

        if tuf.conf.METADATA_FORMAT == 'json':
            manifest = manifest_json

        else:  # Use ASN.1/DER
            assert tuf.conf.METADATA_FORMAT == 'der'  # Or test code is broken/old.

            manifest_fname = os.path.join(SAMPLES_DIR,
                                          'sample_vehicle_manifest.der')
            with open(manifest_fname, 'rb') as fobj:
                manifest = fobj.read()

        # Make sure we're starting off with no registered ECU or vehicle manifests,
        # for any vehicles or ECUs, before the next tests.
        # (If you move ECU Manifest tests before Vehicle Manifest tests, of course,
        # the ECU Manifest check here will have to move elsewhere, as the dict
        # of ECU Manifests registered probably won't be empty.)
        for ecu_serial in inventory.ecu_manifests:
            self.assertFalse(inventory.ecu_manifests[ecu_serial])
        for vin in inventory.vehicle_manifests:
            self.assertFalse(inventory.vehicle_manifests[vin])

        # TODO: Register a vehicle manifest with NO ECU Manifests (unlike the one
        # above) and run these tests after it:
        # self.assertIn('democar', inventory.vehicle_manifests)
        # self.assertTrue(inventory.get_vehicle_manifests('democar'))
        # # No ECU Manifests have been registered yet, since the
        # self.assertIsNone(inventory.get_last_ecu_manifest('TCUdemocar'))
        # # This next one is a little subtle: even if there were no ECU Manifests
        # # submitted in any vehicle manifests yet, the dictionary of ECU Manifests
        # # provided should still not be totally empty if a Vehicle Manifest has been
        # # received: it will look something like this, listing an empty list of
        # # ECU Manifests for each ECU in the car:
        # # {'ecu1_in_car': [], 'ecu2_in_car': [], ...}
        # self.assertTrue(inventory.get_all_ecu_manifests_from_vehicle('democar'))

        # Try a normal vehicle manifest submission, expecting success.
        TestDirector.instance.register_vehicle_manifest(
            'democar', 'INFOdemocar', manifest)

        # Make sure that the vehicle manifest now shows up in the
        # inventorydb, that the various get functions return its data, and that
        # the ECU Manifest within now shows up in the inventorydb.
        self.assertIn('democar', inventory.vehicle_manifests)
        self.assertTrue(inventory.get_vehicle_manifests('democar'))

        # TODO: Check that the value of the Vehicle Manifest retrieved from the
        # inventory db is equivalent to the Vehicle Manifest submitted. This is
        # fairly easy for JSON, but a little trickier for ASN.1/DER, because it is
        # stored in the inventory db as JSON-compatible (not as DER, because there
        # is no longer a particularly good reason to store it as DER at that point).

        # Try reporting the wrong Primary ECU Serial, expecting a spoofing error.
        with self.assertRaises(uptane.Spoofing):
            TestDirector.instance.register_vehicle_manifest(
                'democar', 'TCUdemocar', manifest)
        with self.assertRaises(uptane.Spoofing):
            TestDirector.instance.register_vehicle_manifest(
                'democar', 'nonexistent_ecu_serial', manifest)

        # Try reporting an unknown VIN.
        with self.assertRaises(uptane.UnknownVehicle):
            TestDirector.instance.register_vehicle_manifest(
                'nonexistent_vin', 'INFOdemocar', manifest)

        # Send a partial or badly formatted manifest.
        if tuf.conf.METADATA_FORMAT == 'json':
            # Exclude the signatures portion.
            manifest_bad = copy.deepcopy(manifest['signed'])
            with self.assertRaises(tuf.FormatError):
                TestDirector.instance.register_vehicle_manifest(
                    'democar', 'INFOdemocar', manifest_bad)

        else:
            assert tuf.conf.METADATA_FORMAT == 'der'  # Or test code is broken/old

            # Send a corrupted manifest. Expect decoding error.
            manifest = b'\x99\x99\x99\x99\x99' + manifest[5:]
            with self.assertRaises(uptane.FailedToDecodeASN1DER):
                TestDirector.instance.register_vehicle_manifest(
                    'democar', 'INFOdemocar', manifest)

            # Send an empty manifest. Expect decoding error.
            manifest = bytes()
            with self.assertRaises(uptane.FailedToDecodeASN1DER):
                TestDirector.instance.register_vehicle_manifest(
                    'democar', 'INFOdemocar', manifest)

        # Prepare a manifest with a bad signature.

        if tuf.conf.METADATA_FORMAT == 'json':
            # If using JSON, just corrupt the signature value.
            manifest_bad = copy.deepcopy(manifest_json)
            manifest_bad['signatures'][0]['sig'] = \
                '1234567890abcdef9f1b74d72eb500e4ff0f443f824b83405e2b21264778d1610e0a5f2663b90eda8ab05a28b5b64fc15514020985d8a93576fe33b287e1380f'

            # Try registering the bad-signature manifest.
            with self.assertRaises(tuf.BadSignatureError):
                TestDirector.instance.register_vehicle_manifest(
                    'democar', 'INFOdemocar', manifest_bad)

        else:
            assert tuf.conf.METADATA_FORMAT == 'der'  # Or test code is broken/old.

            # TODO: Add a test using a bad signature. Note that there is already a
            # test below for the *wrong* signature, but it would be good to test
            # both for the wrong signature and for a corrupt signature.
            # So send a properly-encoded manifest with a signature that is produced
            # by the right key, but which does not match the data in the manifest.

            pass

        # Prepare a manifest with the *wrong* signature - a signature from the
        # wrong key that is otherwise correctly signed.
        if tuf.conf.METADATA_FORMAT == 'json':
            # If using JSON, just corrupt the key ID.
            manifest_bad = copy.deepcopy(manifest_json)
            manifest_bad['signatures'][0]['keyid'] = \
                '1234567890abcdef29bfbff1c1c75df59f154fbc45539b2eb30c8a867843b2cb'

        else:
            assert tuf.conf.METADATA_FORMAT == 'der'  # Or test code is broken/old.
            # When using DER, we can convert JSON to DER and re-sign with the wrong
            # key to achieve a similar test.
            manifest_bad = asn1_codec.convert_signed_metadata_to_der(
                manifest_json,
                resign=True,
                datatype='vehicle_manifest',
                private_key=demo.import_private_key('directortimestamp'))

        # Try registering the bad-signature manifest.
        with self.assertRaises(tuf.BadSignatureError):
            TestDirector.instance.register_vehicle_manifest(
                'democar', 'INFOdemocar', manifest_bad)

        # Send Vehicle Manifest containing an ECU Manifest with an unknown
        # ECU Serial. Expect no error, and expect the Vehicle Manifest to be
        # registered, but the particular ECU Manifest to not be registered.

        # First, make sure the ECU Serial in question is not registered.
        with self.assertRaises(uptane.UnknownECU):
            inventory.check_ecu_registered('unknown_ecu')

        if tuf.conf.METADATA_FORMAT == 'json':
            manifest_bad = json.load(
                open(
                    os.path.join(
                        TEST_DATA_DIR, 'flawed_manifests',
                        'vm2_contains_one_unknown_ecu_manifest.json')))
        else:
            assert tuf.conf.METADATA_FORMAT == 'der'  # Or test code is broken/old.
            manifest_bad = open(
                os.path.join(TEST_DATA_DIR, 'flawed_manifests',
                             'vm2_contains_one_unknown_ecu_manifest.der'),
                'rb').read()

        TestDirector.instance.register_vehicle_manifest(
            'democar', 'INFOdemocar', manifest_bad)

        # Now check to make sure the data for an unknown ECU wasn't saved as its
        # own ECU Manifest.
        self.assertNotIn(
            'unknown_ecu',
            inventory.get_all_ecu_manifests_from_vehicle('democar'))
        with self.assertRaises(uptane.UnknownECU):
            inventory.get_last_ecu_manifest('unknown_ecu')
        with self.assertRaises(uptane.UnknownECU):
            inventory.get_ecu_manifests('unknown_ecu')

        # Check to make sure the vehicle manifest itself was saved, though.
        self.assertIn(
            'unknown_ecu',
            inventory.get_last_vehicle_manifest('democar')['signed']
            ['ecu_version_manifests'])

        # Provide a vehicle manifest that is correctly signed by the Primary, but
        # which contains a single ECU Manifest, that ECU Manifest being signed by
        # the wrong key.
        # Ensure that the Vehicle Manifest is saved, but that the ECU Manifest it
        # contains is not saved on its own as a valid ECU Manifest.
        previous_vehicle_manifest = inventory.get_last_vehicle_manifest(
            'democar')
        previous_ecu_manifest = inventory.get_last_ecu_manifest('TCUdemocar')
        n_vms_before = len(inventory.get_vehicle_manifests('democar'))
        n_ems_before = len(inventory.get_ecu_manifests('TCUdemocar'))

        if tuf.conf.METADATA_FORMAT == 'json':
            manifest_bad = json.load(
                open(
                    os.path.join(
                        TEST_DATA_DIR, 'flawed_manifests',
                        'vm3_ecu_manifest_signed_with_wrong_key.json')))
        else:
            assert tuf.conf.METADATA_FORMAT == 'der'  # Or test code is broken/old.
            manifest_bad = open(
                os.path.join(TEST_DATA_DIR, 'flawed_manifests',
                             'vm3_ecu_manifest_signed_with_wrong_key.der'),
                'rb').read()

        TestDirector.instance.register_vehicle_manifest(
            'democar', 'INFOdemocar', manifest_bad)

        # If the latest vehicle manifest is no longer the same as the latest before
        # the test, then a vehicle manifest has been correctly saved.
        self.assertNotEqual(previous_vehicle_manifest,
                            inventory.get_last_vehicle_manifest('democar'))
        # But we must also be sure that the bad manifest has not been saved.
        self.assertEqual(previous_ecu_manifest,
                         inventory.get_last_ecu_manifest('TCUdemocar'))
        # Redundant test in case of code changes:
        self.assertEqual(n_vms_before + 1,
                         len(inventory.get_vehicle_manifests('democar')))
        self.assertEqual(n_ems_before,
                         len(inventory.get_ecu_manifests('TCUdemocar')))

        # TODO: Provide a vehicle manifest that is correctly signed by the
        # Primary, but which contains one untrustworthy ECU Manifest and one
        # trustworthy ECU Manifest. Expected behavior is to accept the Vehicle
        # Manifest and any valid ECU Manifests, and reject the untrustworthy
        # ECU Manifest. Call get functions to confirm.

        # Send a Vehicle Manifest containing an ECU Manifest that has an attack
        # detected report.
        previous_vehicle_manifest = inventory.get_last_vehicle_manifest(
            'democar')
        previous_ecu_manifest = inventory.get_last_ecu_manifest('TCUdemocar')
        n_vms_before = len(inventory.get_vehicle_manifests('democar'))
        n_ems_before = len(inventory.get_ecu_manifests('TCUdemocar'))

        if tuf.conf.METADATA_FORMAT == 'json':
            manifest = json.load(
                open(
                    os.path.join(TEST_DATA_DIR, 'flawed_manifests',
                                 'vm4_attack_detected_in_ecu_manifest.json')))
        else:
            assert tuf.conf.METADATA_FORMAT == 'der'  # Or test code is broken/old.
            manifest = open(
                os.path.join(TEST_DATA_DIR, 'flawed_manifests',
                             'vm4_attack_detected_in_ecu_manifest.der'),
                'rb').read()

        TestDirector.instance.register_vehicle_manifest(
            'democar', 'INFOdemocar', manifest)

        self.assertNotEqual(previous_vehicle_manifest,
                            inventory.get_last_vehicle_manifest('democar'))
        # But we must also be sure that the bad manifest has not been saved.
        self.assertNotEqual(previous_ecu_manifest,
                            inventory.get_last_ecu_manifest('TCUdemocar'))
        # Redundant test in case of code changes:
        self.assertEqual(n_vms_before + 1,
                         len(inventory.get_vehicle_manifests('democar')))
        self.assertEqual(n_ems_before + 1,
                         len(inventory.get_ecu_manifests('TCUdemocar')))

        # Expect the attack report string in the registered manifests.
        self.assertEqual(
            'some attack detected',
            inventory.get_last_vehicle_manifest(
                'democar')['signed']['ecu_version_manifests']['TCUdemocar'][0]
            ['signed']['attacks_detected'])

        self.assertEqual(
            'some attack detected',
            inventory.get_last_ecu_manifest('TCUdemocar')['signed']
            ['attacks_detected'])
Esempio n. 26
0
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()