### Example Director Targets Metadata Structure (JSON) Source: https://context7.com/uptane/uptane-standard/llms.txt Illustrates the structure of the Targets metadata generated by the Director repository, including details for specific ECUs, file hashes, lengths, and custom attributes like hardware IDs and encryption status. This JSON object serves as an example of the output from the `direct_installation` function. ```json { "signatures": [{"keyid": "director_targets_key", "sig": "..."}], "signed": { "_type": "Targets", "expires": "2024-12-31T23:59:59Z", "version": 156, "targets": { "engine_ecu_v3.2.bin": { "length": 2097152, "hashes": { "sha256": "abc123...", "sha512": "def456..." }, "custom": { "ecuIdentifier": "ENGINE_ECU_001", # Target specific ECU "hardwareIds": ["HW_ENGINE_V2", "HW_ENGINE_V3"], "releaseCounter": 67, "encrypted": False } }, "brake_ecu_v2.1.bin": { "length": 1048576, "hashes": {"sha256": "xyz789..."}, "custom": { "ecuIdentifier": "BRAKE_ECU_002", "hardwareIds": ["HW_BRAKE_V1"], "releaseCounter": 34, "encrypted": True, "encryptionInfo": { "symmetricKey": "encrypted_aes_key_base64", "algorithm": "AES-256-CBC" } } } } } } ``` -------------------------------- ### Python Usage Example for Delegation Resolution Source: https://context7.com/uptane/uptane-standard/llms.txt Demonstrates how to use the `resolve_delegations` function with specific image file path, hardware ID, and the example metadata. It includes error handling for `SecurityError` that might occur during metadata verification or resolution. ```python # Usage: resolve delegation for specific image try: image_metadata = resolve_delegations( image_filepath="supplier1/engine/v3.2.bin", hardware_id="HW_ENGINE_V2", current_role_metadata=image_targets_with_delegation ) if image_metadata: print(f"Found valid metadata: {image_metadata}") else: print("No valid metadata found") except SecurityError as e: print(f"Delegation resolution failed: {e}") ``` -------------------------------- ### Verify and Install ECU Image (Python) Source: https://context7.com/uptane/uptane-standard/llms.txt This Python pseudocode implements the image verification and installation procedure as described in UPTANE sections 5.4.4.4 and 5.4.4.5. It loads director metadata, checks ECU and hardware compatibility, performs rollback protection, downloads and decrypts the image if necessary, verifies hashes and length, and finally installs the image after preconditions are met. Dependencies include functions for loading metadata, downloading images, encryption/decryption, hashing, and installation. ```python def verify_and_install_image(ecu_id, ecu_hardware_id): """ Image verification procedure per section 5.4.4.4 and installation per 5.4.4.5. Args: ecu_id: Unique ECU identifier ecu_hardware_id: Hardware identifier for compatibility check Returns: bool: True if verification and installation succeed """ # Load latest Director Targets metadata targets = load_metadata("targets", "director") # Find target for this ECU target = None for t in targets.signed.targets: if t.custom.get("ecuIdentifier") == ecu_id: target = t break if not target: print("No update available for this ECU") return False # Check hardware compatibility if ecu_hardware_id not in target.custom.get("hardwareIds", []): raise SecurityError(f"Incompatible hardware: {ecu_hardware_id}") # Check release counter (rollback protection) previous_target = load_previous_target(ecu_id) if previous_target and target.custom.get("releaseCounter", 0) < previous_target.custom.get("releaseCounter", 0): raise SecurityError("Rollback attack: release counter decreased") # Download image (or load from storage) image_path = construct_image_filename(target) image_data = download_image(image_path, target.length) # Handle encrypted images if target.custom.get("encrypted", False): encryption_info = target.custom.get("encryptionInfo") image_data = decrypt_image(image_data, ecu_key, encryption_info) # Verify all hashes for hash_type, expected_hash in target.hashes.items(): computed_hash = compute_hash(image_data, hash_type) if computed_hash != expected_hash: raise SecurityError(f"{hash_type} hash mismatch") # Verify length if len(image_data) != target.length: raise SecurityError("Image length mismatch") # Create backup before installation backup_current_image() # Install when preconditions met (e.g., vehicle parked) if installation_preconditions_met(): install_image(image_data) print(f"Successfully installed {target.filepath}") return True else: print("Waiting for safe installation conditions") return False # Example usage with error handling try: success = verify_and_install_image("ECU_12345", "HW_V1") # Create version report after installation attempt version_report = create_ecu_version_report( ecu_id="ECU_12345", installed_image=get_installed_image(), attacks_detected=[], current_time=get_secure_time(), nonce=generate_unique_nonce() ) send_to_primary(version_report) except SecurityError as e: # Report attack and keep current image version_report = create_ecu_version_report( ecu_id="ECU_12345", installed_image=get_installed_image(), attacks_detected=[str(e)], current_time=get_secure_time(), nonce=generate_unique_nonce() ) send_to_primary(version_report) ``` -------------------------------- ### Python Example Image Repository Metadata with Delegations Source: https://context7.com/uptane/uptane-standard/llms.txt An example structure for UPTANE image repository metadata, including top-level delegations. This structure defines which roles (identified by key IDs, paths, and hardware IDs) are authorized to sign specific firmware files. It demonstrates the use of `terminating` flags to control the delegation search. ```python image_targets_with_delegation = { "signatures": [{"keyid": "image_targets_key", "sig": "..."}], "signed": { "_type": "Targets", "expires": "2024-12-31T23:59:59Z", "version": 89, "targets": {}, # Top-level has no direct targets "delegations": { "keys": { "supplier1_key": { "keytype": "ed25519", "keyval": {"public": "..."} } }, "roles": [ { "name": "supplier1-engine-firmware", "keyids": ["supplier1_key"], "threshold": 1, "paths": ["supplier1/engine/*.bin"], "hardware_ids": ["HW_ENGINE_V2", "HW_ENGINE_V3"], "terminating": False }, { "name": "supplier2-brake-firmware", "keyids": ["supplier2_key"], "threshold": 1, "paths": ["supplier2/brake/*.bin"], "hardware_ids": ["HW_BRAKE_V1"], "terminating": True # Do not search beyond this } ] } } } ``` -------------------------------- ### Build Documentation with Docker Source: https://context7.com/uptane/uptane-standard/llms.txt Generates documentation artifacts, including HTML and plaintext versions, without requiring local installation of tools. It leverages Docker containers to perform the conversion from markdown to XML and then to HTML or plaintext, ensuring a consistent build environment. ```bash # Build HTML using Docker (no local dependencies required) make html-docker # This uses the uptane/rfc2629 Docker image to: # 1. Convert markdown to XML # 2. Convert XML to HTML # 3. Strip unnecessary RFC header information # Build plaintext version using Docker make plaintext-docker # Expected output: uptane-standard.txt plaintext document # Useful for reading the standard in terminal or text editors ``` -------------------------------- ### Root Metadata Verification (Python Pseudocode) Source: https://context7.com/uptane/uptane-standard/llms.txt Illustrates the pseudocode for verifying Root metadata, a critical step for Primary ECUs to establish trust in repository signing keys and prevent arbitrary software attacks. It handles version checking for rollback protection and expiration checks for freeze attack prevention. ```python # Pseudocode for Root metadata verification def check_root_metadata(repository_type): """ Verifies Root metadata following section 5.4.4 of the standard. Args: repository_type: Either "director" or "image" Returns: bool: True if verification succeeds, False otherwise """ # Load previous Root metadata previous_root = load_metadata("root", repository_type) N = previous_root.version # Try updating to newer versions while True: try: # Download next version new_root = download_metadata(f"{N+1}.root.json", repository_type) # Check signature with keys from both old and new Root if not verify_signatures(new_root, previous_root.keys, previous_root.threshold): raise SecurityError("Arbitrary software attack detected") if not verify_signatures(new_root, new_root.keys, new_root.threshold): raise SecurityError("Arbitrary software attack detected") # Check version number (rollback protection) if new_root.version != N + 1: raise SecurityError("Rollback attack detected") # Update state previous_root = new_root N = new_root.version except FileNotFoundError: # No newer version available break # Check expiration (freeze attack protection) current_time = get_secure_time() if current_time > previous_root.expires: raise SecurityError("Freeze attack detected") # Check for key rotation if keys_rotated(previous_root, ["timestamp", "snapshot"]): delete_metadata(["timestamp", "snapshot"]) return True # Example usage for Primary ECU try: check_root_metadata("director") check_root_metadata("image") print("Root metadata verification successful") except SecurityError as e: print(f"Security attack detected: {e}") abort_update_cycle() ``` -------------------------------- ### Construct Vehicle Version Manifest (Python) Source: https://context7.com/uptane/uptane-standard/llms.txt This function constructs a signed vehicle version manifest as detailed in UPTANE section 5.4.1.1. It collects version reports from secondary ECUs, generates its own report, and then signs the combined payload using the primary ECU's key. It requires helper functions for getting ECU details, time, nonces, and for hashing and signing. ```python def construct_vehicle_manifest(primary_ecu_id, vehicle_id, secondary_ecus): """ Constructs a vehicle version manifest per section 5.4.1.1. Args: primary_ecu_id: Unique identifier for Primary ECU vehicle_id: Vehicle identification (e.g., VIN) secondary_ecus: List of Secondary ECU objects Returns: dict: Signed vehicle version manifest """ ecu_version_reports = [] # Collect version reports from Secondaries for secondary in secondary_ecus: version_report = secondary.get_version_report() ecu_version_reports.append(version_report) # Create Primary's own version report primary_report = create_ecu_version_report( ecu_id=primary_ecu_id, installed_image=get_installed_image(), attacks_detected=[], # List any detected attacks current_time=get_secure_time(), nonce=generate_unique_nonce() # Prevent replay attacks ) ecu_version_reports.append(primary_report) # Construct payload payload = { "vin": vehicle_id, "primary_ecu_serial": primary_ecu_id, "ecu_version_reports": ecu_version_reports } # Sign manifest with Primary's ECU key payload_hash = hash_payload(payload) signature = sign_with_ecu_key(payload_hash) manifest = { "signatures": [{ "keyid": get_ecu_key_id(primary_ecu_id), "method": "ed25519", "hash": payload_hash, "hash_function": "sha256", "sig": signature }], "signed": payload } return manifest ```