Crypto: - Replace broken ChaCha20 (static nonce) with ChaCha20-Poly1305 AEAD - HKDF-SHA256 key derivation from per-device factory NVS master keys - Random 12-byte nonce per message (ESP32 hardware RNG) - crypto_init/encrypt/decrypt API with mbedtls legacy (ESP-IDF v5.3.2) - Custom partition table with factory NVS (fctry at 0x10000) Firmware: - crypto.c full rewrite, messages.c device_id prefix + AEAD encrypt - crypto_init() at boot with esp_restart() on failure - Fix command_t initializations across all modules (sub/help fields) - Clean CMakeLists dependencies for ESP-IDF v5.3.2 C3PO (C2): - Rename tools/c2 + tools/c3po -> tools/C3PO - Per-device CryptoContext with HKDF key derivation - KeyStore (keys.json) for master key management - Transport parses device_id:base64(...) wire format Tools: - New tools/provisioning/provision.py for factory NVS key generation - Updated flasher with mbedtls config for v5.3.2 Docs: - Update all READMEs for new crypto, C3PO paths, provisioning - Update roadmap, architecture diagrams, security sections - Update CONTRIBUTING.md project structure
47 lines
1.4 KiB
Python
47 lines
1.4 KiB
Python
"""Authentication decorators for Flask routes."""
|
|
|
|
import hmac
|
|
from functools import wraps
|
|
from flask import session, redirect, url_for, request, jsonify
|
|
|
|
|
|
def create_auth_decorators(get_multilat_token):
|
|
"""
|
|
Create auth decorators with access to server config.
|
|
|
|
Args:
|
|
get_multilat_token: Callable that returns the MLAT API token
|
|
|
|
Returns:
|
|
Tuple of (require_login, require_api_auth) decorators
|
|
"""
|
|
|
|
def require_login(f):
|
|
"""Decorator requiring user to be logged in via session."""
|
|
@wraps(f)
|
|
def decorated(*args, **kwargs):
|
|
if not session.get("logged_in"):
|
|
return redirect(url_for("pages.login"))
|
|
return f(*args, **kwargs)
|
|
return decorated
|
|
|
|
def require_api_auth(f):
|
|
"""Decorator requiring session login OR Bearer token."""
|
|
@wraps(f)
|
|
def decorated(*args, **kwargs):
|
|
# Session auth
|
|
if session.get("logged_in"):
|
|
return f(*args, **kwargs)
|
|
|
|
# Bearer token auth
|
|
auth_header = request.headers.get("Authorization", "")
|
|
if auth_header.startswith("Bearer "):
|
|
token = auth_header[7:]
|
|
if hmac.compare_digest(token, get_multilat_token()):
|
|
return f(*args, **kwargs)
|
|
|
|
return jsonify({"error": "Unauthorized"}), 401
|
|
return decorated
|
|
|
|
return require_login, require_api_auth
|