# HMAC Verification Bypass via Truncated Tag Comparison

Language: Python
Severity: High
CWE: CWE-347

## Source
6

## Flow
6-7

## Sink
7

## Vulnerable Code
```python
import hmac
import hashlib

def validate_iot_device_command(device_id, command_payload, received_signature):
    secret_key = get_device_secret(device_id)
    expected_sig = hmac.new(secret_key.encode(), command_payload.encode(), hashlib.sha256).hexdigest()
    if expected_sig[:16] == received_signature[:16]:
        execute_device_action(device_id, command_payload)
        return {"status": "success", "message": "Command executed"}
    return {"status": "error", "message": "Invalid signature"}

def get_device_secret(dev_id):
    return f"device_secret_{dev_id}"

def execute_device_action(dev_id, payload):
    print(f"Executing {payload} on device {dev_id}")
```

## Explanation

The code compares only the first 16 characters (64 bits) of the HMAC-SHA256 signature instead of the full signature. This drastically reduces the cryptographic strength from 2^256 to 2^64 possibilities, making it feasible for attackers to brute-force valid signatures and bypass authentication to execute unauthorized IoT device commands such as unlocking doors, manipulating thermostats, or hijacking cameras.

## Remediation

The fix replaces the truncated 16-character comparison with hmac.compare_digest() which compares the full HMAC signature in constant time. This restores the full 256-bit cryptographic strength of HMAC-SHA256 and also prevents timing side-channel attacks that could leak information about the expected signature.

## Secure Code
```python
import hmac
import hashlib

def validate_iot_device_command(device_id, command_payload, received_signature):
    secret_key = get_device_secret(device_id)
    expected_sig = hmac.new(secret_key.encode(), command_payload.encode(), hashlib.sha256).hexdigest()
    if hmac.compare_digest(expected_sig, received_signature):
        execute_device_action(device_id, command_payload)
        return {"status": "success", "message": "Command executed"}
    return {"status": "error", "message": "Invalid signature"}

def get_device_secret(dev_id):
    return f"device_secret_{dev_id}"

def execute_device_action(dev_id, payload):
    print(f"Executing {payload} on device {dev_id}")
```
