01 · Completar la operación OTA
Autorización y aceptación operativa
El tema 43 llevó una imagen hasta su primer arranque. Ahora distinguimos la autorización del código de su aceptación operativa. Una imagen legítimamente firmada puede contener un error; una imagen que funciona puede provenir de una fuente no autorizada. Se necesitan ambos controles.
| Control | Pregunta | Límite |
|---|---|---|
| Integridad | ¿El contenido coincide con el esperado? | No identifica por sí sola quién lo autorizó |
| Firma y política de claves | ¿Lo autorizó una clave aceptada para ese propósito? | No demuestra ausencia de errores |
| Compatibilidad | ¿Corresponde a este hardware y sus dependencias? | No prueba salud de esta unidad |
| Diagnóstico de arranque | ¿Satisface los criterios locales de aceptación? | No detecta necesariamente errores tardíos |
| Reversión | ¿Hay una aplicación anterior que todavía pueda operar? | Depende de imágenes, datos y política de seguridad |
La disponibilidad de dos copias de firmware ayuda, pero no garantiza una recuperación completa. El respaldo debe seguir siendo auténtico, elegible y compatible con los datos que encontrará. Además, el hardware mantiene las condiciones seguras del producto durante el reinicio y la recuperación.
El laboratorio empieza con una imagen ya descargada. Simula las decisiones posteriores y el estado de dos slots. No implementa algoritmos criptográficos, no modifica flash y no programa eFuses.
02 · Autorizar el artefacto correcto
Qué garantiza una firma
La firma digital vincula el contenido firmado con una clave privada. El verificador comprueba la firma mediante una clave pública aceptada y las reglas del esquema. No se considera confiable una clave solo porque venga incluida junto con el binario que quiere autorizar.
→ comprobación de autenticidad e integridad del contenido cubierto
La clave privada de publicación se protege fuera de la flota. Los dispositivos necesitan el material de verificación correspondiente; no necesitan la clave que permite firmar versiones. Tampoco se reutiliza la credencial operativa de equipo07 como autoridad de publicación de firmware.
Qué contenido queda cubierto
Se verifica el formato exacto que define la plataforma: imagen, cabeceras, relleno o bloque de firma según corresponda. No se inventa un protocolo concatenando una contraseña con el archivo y calculando un hash. La biblioteca y las herramientas oficiales realizan la comprobación criptográfica.
La política también vincula el artefacto con su producto, dependencias y restricciones. Si un manifiesto decide el destino o la aplicabilidad, sus campos críticos necesitan protección y relación inequívoca con la imagen. Firmar un binario y aceptar metadatos modificables que lo asignen a cualquier placa deja decisiones importantes sin proteger.
RFC 9124 describe un modelo de información para manifiestos, incluyendo identidad, condiciones y secuencia. Es una referencia para diseñar la información protegida; los perfiles de esta lección son una simplificación propia.
Firma válida, versión no admitida
Una imagen antigua puede conservar una firma correcta y tener una vulnerabilidad conocida. La firma demuestra una autorización bajo una política de claves, no que sea la publicación que corresponde instalar hoy. Se necesitan controles de versión, secuencia y nivel mínimo según el producto.
La firma tampoco es cifrado: el contenido firmado puede seguir siendo público. Confidencialidad de distribución, autenticidad y protección del almacenamiento son objetivos diferentes.
03 · Desde una raíz aceptada hasta la aplicación
Claves y cadena de arranque
Verificar al recibir una actualización protege esa ruta de instalación. La verificación durante el arranque busca que el código ejecutado respete la cadena de confianza prevista. Si alguien puede reemplazar el verificador o el material que decide qué aceptar, una firma del archivo no resuelve por sí sola ese escenario.
En plataformas compatibles, Secure Boot v2 de Espressif verifica componentes de arranque y aplicaciones firmadas. El soporte y sus condiciones dependen del chip y revisión; la documentación para ESP32 clásico especifica revisión 3.0 o posterior.
La misma documentación distingue verificación de aplicaciones firmadas durante OTA sin Secure Boot por hardware. Ese modo no ofrece la misma protección frente a un atacante que puede escribir flash. Se elige el mecanismo según el escenario y las capacidades reales.
Cadena de confianza
Define qué componente verifica al siguiente, dónde reside la autoridad y cómo se impide sustituirla por material arbitrario.
Salud operativa
Define qué debe funcionar después de arrancar y qué se hace si falla. Un boot autenticado todavía puede ejecutar una versión defectuosa.
Producción y mantenimiento de claves
El proceso de publicación limita quién solicita una firma y para qué producto. Conserva evidencia del artefacto aprobado y separa las tareas de construcción, aprobación y acceso a la clave cuando la operación lo requiere.
También contempla pérdida o compromiso de una clave. La rotación y revocación de autoridades dependen de lo que el hardware y el formato permitan; no se presume que toda placa pueda incorporar claves nuevas sin límites. Se verifica que las imágenes de recuperación sigan aceptándose después de un cambio.
Las protecciones de fabricación y su configuración se ensayan en el entorno previsto antes de desplegar. Esta lección no incluye comandos para programar eFuses ni cambiar interfaces de recuperación.
04 · Imágenes y estado son cosas distintas
Particiones y metadatos
Un esquema de dos slots conserva una aplicación conocida mientras prepara otra en el destino inactivo. Los metadatos indican qué se debe arrancar y qué estado tiene cada imagen. Esos metadatos también necesitan consistencia frente a cortes.
La tabla de particiones de ESP-IDF describe regiones y subtipos. Este CSV ilustrativo reserva dos slots de 1,5 MiB en una flash de 4 MiB, suponiendo la tabla en 0x8000:
# Name, Type, SubType, Offset, Size
nvs, data, nvs, 0x9000, 0x6000
otadata, data, ota, 0xf000, 0x2000
phy_init, data, phy, 0x11000, 0x1000
ota_0, app, ota_0, 0x20000, 0x180000
ota_1, app, ota_1, 0x1a0000, 0x180000No es una configuración universal. Se valida tamaño de flash, alineación, tamaño final firmado, bootloader y todas las regiones del producto. Si cambia el offset de la tabla, se recalcula el mapa completo. El archivo no incluye una partición factory ni prescribe activar anti-rollback.
Qué protege el respaldo
No se usa el slot de la aplicación que está ejecutándose como destino de descarga. Tampoco se borra el respaldo para ganar espacio mientras el candidato sigue en prueba. Con dos slots, comenzar la siguiente actualización reutiliza uno: el diseño debe saber qué copia deja de conservar.
El laboratorio abstrae tamaños, borrado y escritura como una transición de instalación. El tema 43 desarrolla transferencia y capacidad. Aquí interesa que una imagen nueva, una pendiente y una válida tengan significados diferentes.
05 · Evidencia antes de aceptar
Primer arranque y salud
El primer arranque inicia una etapa acotada de prueba. La aplicación verifica las condiciones esenciales del producto y confirma su aceptación solo cuando tiene evidencia suficiente. Una pantalla de bienvenida o el primer mensaje de log no prueban que el equipo pueda operar.
| Área | Ejemplo de evidencia | Cuidado |
|---|---|---|
| Configuración | Estructura legible, versión y valores válidos | No sustituir automáticamente datos esenciales por valores peligrosos |
| Almacenamiento | Estado coherente y acceso a los datos necesarios | Una prueba debe respetar desgaste y consistencia |
| Control local | Tareas dentro de plazo y salidas inicializadas apropiadamente | No accionar una carga peligrosa para demostrar salud |
| Periféricos esenciales | Identificación y lecturas admitidas por la política | Distinguir fallo de firmware de una desconexión física previa |
| Comunicación | Pila local y contratos requeridos por el producto | La caída de un servicio externo no siempre justifica revertir |
Un diagnóstico con plazo
Se define un límite para la prueba y qué hacer ante cada resultado. Un watchdog detecta ciertas faltas de progreso, pero no identifica todos los fallos funcionales. Una tarea puede alimentar al watchdog mientras devuelve mediciones equivocadas.
Si los criterios incluyen un servicio remoto, se contempla que la red esté caída antes de actualizar. Revertir repetidamente por una falla externa puede dejar al equipo en un ciclo sin resolverla. El producto diferencia salud esencial local, comunicación y observación de plataforma.
Confirmación durable
La confirmación cambia la política de arranque. Se comprueba su retorno y no se anuncia aceptación si la persistencia falló. El diagnóstico corresponde al firmware y al arranque actuales; no se recupera un flag de éxito de la versión anterior para confirmar la nueva.
En el modelo, salud resume evidencia local. La acción diagnosticar registra que esa prueba pasó; confirmar vuelve a exigir condiciones válidas y persistencia. No es un campo que la nube pueda marcar para saltar controles del equipo.
06 · Recuperar servicio, no solo cambiar de slot
Volver a una aplicación conocida
La reversión abandona un candidato no aceptado y busca una aplicación anterior admisible. Para ser una recuperación operativa, esa aplicación también debe poder trabajar con la configuración y los datos que quedaron.
| Evento | Respuesta prevista |
|---|---|
| El candidato no supera la comprobación de arranque | No ejecutar ese candidato; buscar una alternativa admisible |
| Declara un fallo esencial durante la prueba | Rechazarlo y aplicar la ruta de reversión prevista |
| Se reinicia sin confirmar | No asumir aceptación por haber arrancado una vez |
| Diagnóstico y aceptación terminan bien | Conservar el candidato como aplicación confirmada |
| No queda una aplicación operativa admisible | Entrar en recuperación autorizada y mantener condiciones locales seguras |
En ESP-IDF, la reversión de aplicación se configura con CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE. Los estados de OTA distinguen la aplicación nueva, pendiente de verificar y válida. Un reinicio sin aceptación durante la prueba puede descartar el candidato y seleccionar una alternativa.
Eso no crea un respaldo inexistente. Se comprueba que haya otra aplicación arrancable bajo la política vigente. Un binario vacío, corrupto o prohibido por seguridad no sirve como salida de emergencia.
Fallas después de confirmar
La confirmación termina la protección de prueba inicial de ese candidato. No se presume que un error semanas después vaya a activar la misma reversión automáticamente. La respuesta a fallos tardíos puede requerir otra publicación, una acción de gestión autorizada o un procedimiento local de recuperación.
El laboratorio permite declarar fallido únicamente un candidato en prueba. La recuperación es un estado final del ejercicio: no incluye un botón que elimine controles de firma o de seguridad para volver a arrancar.
07 · Evitar volver a una vulnerabilidad conocida
Reversión y anti-rollback
La reversión busca mantener disponibilidad. La protección contra retroceso, o anti-rollback, evita ejecutar versiones con un nivel de seguridad inferior al mínimo aceptado. Pueden convivir si existe un respaldo que satisfaga ambas políticas.
+ nivel de seguridad ≥ mínimo vigente
+ compatibilidad con datos y entorno
El número de build identifica una construcción; el nivel de seguridad representa una política diferente. Se pueden publicar varios builds con el mismo nivel. Un build con número mayor no es admisible si su nivel de seguridad está por debajo del mínimo que exige el equipo.
La política anti-rollback de ESP-IDF usa una versión de seguridad de imagen y un valor del chip. Con esa configuración, confirmar una aplicación puede actualizar el mínimo aceptado. Sus límites y restricciones se verifican para el chip concreto.
| Momento | Mínimo | A: seguridad 1 | B: seguridad 2 |
|---|---|---|---|
| B todavía en prueba | 1 | Puede ser respaldo, con los demás requisitos | Se evalúa antes de aceptar |
| B confirmada y mínimo elevado | 2 | Queda por debajo de la política | Es la aplicación confirmada |
El momento del cambio importa
Si se elimina demasiado pronto la posibilidad de ejecutar la versión anterior, un fallo del candidato puede dejar al equipo sin una alternativa útil. Se planifican diagnóstico, aceptación y recuperación antes de avanzar el mínimo. La operación real puede involucrar cambios irreversibles: no es un contador de preferencias que se reduzca al reiniciar.
El modelo actualiza el mínimo al confirmar, nunca lo disminuye. Representa una política habilitada desde el comienzo; no reproduce el almacenamiento físico del chip ni todos los puntos de fallo entre metadatos y eFuses. «Nuevo escenario ficticio» crea otro ejercicio, no revierte un cambio real de hardware.
El control de nivel no reemplaza la autorización de una publicación ni la protección contra repetición del manifiesto. El modelo admite builds no crecientes si cumplen sus otras condiciones; la secuencia y las excepciones de instalación de un producto real requieren su propia política.
08 · Lo que no vuelve atrás con el binario
Datos que sobreviven al firmware
Una actualización puede cambiar configuración, índices, calibración o formatos de registro. Esos datos suelen vivir fuera del slot de aplicación. Volver al código anterior no restaura automáticamente su contenido.
Supongamos que A interpreta el esquema 1 y B necesita el 2. B arranca y sobrescribe la única copia en formato 2. Si después falla, A puede conservar una firma válida y aun así no operar porque ya no entiende los datos.
| Estrategia | Qué aporta | Qué se debe probar |
|---|---|---|
| Lectura compatible con ambos formatos | Permite coexistencia durante una transición | Casos antiguos, nuevos y estructuras incompletas |
| Copia nueva y conmutación versionada | Conserva una representación previa durante la prueba | Espacio, cortes y consistencia entre copias |
| Migración por etapas | Separa preparación, uso y retirada del formato anterior | Orden de versiones y unidades que saltean publicaciones |
| Respaldo y restauración autorizados | Ofrece una recuperación explícita | Integridad, compatibilidad, antigüedad y protección de secretos |
Una prueba deliberadamente peligrosa
El perfil «requiere esquema 2» del laboratorio arranca sin poder superar salud mientras los datos sigan en 1. La acción migrar sobrescribe el esquema de la única copia. Si el candidato falla después, la aplicación A del modelo no puede recuperar servicio con esos datos.
La simulación entra entonces en recuperación. Combina elegibilidad de arranque y compatibilidad operativa para mostrar el problema; un bootloader real no tiene por qué entender el esquema de la aplicación. Podría arrancar el binario antiguo y que sea ese código el que descubra que no puede leer su configuración.
La acción no es una recomendación de migración. No modela cortes dentro de una escritura, restauración ni compatibilidad parcial. En el producto se prueban esos casos y se decide qué datos pueden transformarse antes de confirmar y cuáles deben conservarse para una reversión.
09 · Resolver el primer arranque con el SDK
Integración con ESP-IDF
Este fragmento consulta el estado de la aplicación en ejecución y resuelve una prueba pendiente. El diagnóstico local debe haberse realizado con criterios y plazos del producto. El código no realiza OTA, no habilita Secure Boot y no configura por sí mismo la reversión.
#include <stdbool.h>
#include <stddef.h>
#include "esp_err.h"
#include "esp_ota_ops.h"
esp_err_t resolver_primer_arranque(bool diagnostico_local_ok) {
const esp_partition_t *actual = esp_ota_get_running_partition();
if (actual == NULL) return ESP_FAIL;
esp_ota_img_states_t estado;
esp_err_t err = esp_ota_get_state_partition(actual, &estado);
if (err != ESP_OK) return err;
if (estado != ESP_OTA_IMG_PENDING_VERIFY) {
return ESP_OK; // no hay una prueba pendiente que resolver aquí
}
if (diagnostico_local_ok) {
return esp_ota_mark_app_valid_cancel_rollback();
}
if (!esp_ota_check_rollback_is_possible()) {
return ESP_ERR_OTA_ROLLBACK_FAILED;
}
// En éxito, esta llamada inicia la reversión y reinicia.
return esp_ota_mark_app_invalid_rollback_and_reboot();
}Las declaraciones y retornos se contrastan con el encabezado oficial esp_ota_ops.h; se usa el equivalente de la versión instalada. El resultado de check_rollback_is_possible se refiere a la política de imágenes del SDK, no demuestra compatibilidad de los datos de aplicación.
Si devuelve un error, el llamador registra el problema y mantiene la conducta local de recuperación. No continúa como si el firmware hubiera sido aceptado. Incluso cuando no hay estado pendiente, ESP_OK en este fragmento solo significa que no hubo una resolución fallida en esa función; no constituye un certificado general de salud.
Antes de usarlo, se comprueban configuración de bootloader, particiones, firma y política de seguridad del proyecto. No se invoca confirmación al principio de app_main solo para eliminar el estado pendiente. Tampoco se hace una actualización nueva mientras la actual siga sin resolver su prueba.
En el modelo, la aceptación y el mínimo cambian en una transición lógica. La implementación real verifica los retornos del SDK y su comportamiento ante cortes, incluidas las operaciones de seguridad que no equivalen a escribir un archivo común.
10 · Un modelo de aceptación y recuperación
Modelo ejecutable en Python
El registro empieza con A válida, build 1, nivel de seguridad 1 y datos en esquema 1. Instalar representa una descarga completa y comprobada al slot inactivo. El primer reinicio pone el candidato en prueba; otro reinicio sin confirmar intenta la reversión.
Firma, clave confiable, integridad y comprobación de arranque son resultados externos simulados. El estado nueva/pendiente/válida/inválida es una abstracción y no reproduce todos los estados ni la selección exacta de ESP-IDF. Los rechazos conservan el registro; una reversión procesada puede terminar en recuperación si no hay respaldo útil.
Python en el navegador. El programa usa la biblioteca estándar y funciona con Pyodide. Recorre éxito, reinicio sin aceptación, firma rechazada, mínimo de seguridad y migración destructiva, sin tocar hardware.
from copy import deepcopy
def nuevo():
return dict(fase="estable", ejecutando="A", confirmada="A", seleccion=None,
minimo=1, datos=1, diagnostico=False,
slots=dict(A=dict(build=1, seguridad=1, esquema=1,
modelo="placaA", estado="valida"), B=None))
def imagen(perfil):
m = dict(build=2, seguridad=1, esquema=1, modelo="placaA", estado="nueva")
if perfil == "seguridad2": m.update(build=3, seguridad=2)
if perfil == "anterior": m.update(build=4, seguridad=1)
if perfil == "otra_placa": m["modelo"] = "placaB"
if perfil == "migracion": m["esquema"] = 2
return m
def elegible(e, slot):
m = e["slots"][slot] if slot else None
return bool(m and m["estado"] == "valida" and
m["seguridad"] >= e["minimo"] and m["esquema"] == e["datos"])
def aplicar(estado, accion, perfil="normal", firma=True, clave=True,
integridad=True, autorizado=True, persistencia=True,
salud=True, respaldo=True, arranque=True):
e = deepcopy(estado)
def fin(ok, motivo):
return dict(estado=e, ok=ok, motivo=motivo)
def volver(fallida):
e["slots"][fallida]["estado"] = "invalida"
e.update(seleccion=None, diagnostico=False)
anterior = e["confirmada"]
if not respaldo and anterior != fallida:
e["slots"][anterior]["estado"] = "invalida"
if anterior != fallida and elegible(e, anterior):
e.update(ejecutando=anterior, fase="estable")
return fin(True, "Reversión operativa a la versión confirmada compatible")
e.update(ejecutando=None, fase="recuperacion")
return fin(True, "Sin respaldo operativo elegible: requiere recuperación autorizada")
if accion == "reiniciar":
if e["fase"] == "prueba": return volver(e["ejecutando"])
if e["fase"] == "preparada":
destino = e["seleccion"]
if not arranque: return volver(destino)
e.update(ejecutando=destino, seleccion=None, fase="prueba", diagnostico=False)
e["slots"][destino]["estado"] = "pendiente"
return fin(True, "Primer arranque del candidato; todavía no está confirmado")
return fin(True, "Reinicio sin cambio del estado de aceptación")
if accion == "instalar":
if e["fase"] != "estable": return fin(False, "La instalación requiere una aplicación estable")
if not autorizado or not firma or not clave or not integridad:
return fin(False, "Falla autorización, firma, clave confiable o integridad")
m = imagen(perfil)
if m["modelo"] != "placaA": return fin(False, "La firma no reemplaza la compatibilidad de hardware")
if m["seguridad"] < e["minimo"]: return fin(False, "Nivel de seguridad inferior al mínimo aceptado")
if not persistencia: return fin(False, "No se confirmó la escritura y selección durables")
destino = "B" if e["ejecutando"] == "A" else "A"
e["slots"][destino] = m
e.update(seleccion=destino, fase="preparada", diagnostico=False)
return fin(True, "Imagen comprobada en el destino inactivo; conserva la aplicación actual")
if accion == "fallar":
if e["fase"] != "prueba": return fin(False, "Solo se declara fallido un candidato en prueba")
return volver(e["ejecutando"])
if accion == "migrar":
if e["fase"] != "prueba": return fin(False, "La migración del ejercicio requiere un candidato en prueba")
esquema = e["slots"][e["ejecutando"]]["esquema"]
if e["datos"] == esquema: return fin(False, "Los datos ya tienen el esquema requerido")
if not persistencia: return fin(False, "No se confirmó la migración persistida")
e.update(datos=esquema, diagnostico=False)
return fin(True, "Migración destructiva simulada; puede impedir el funcionamiento del respaldo")
if accion in ("diagnosticar", "confirmar"):
if e["fase"] != "prueba": return fin(False, "La aceptación requiere un candidato en prueba")
m = e["slots"][e["ejecutando"]]
if not salud or m["esquema"] != e["datos"]:
return fin(False, "Falla salud local o compatibilidad de los datos")
if accion == "diagnosticar":
e["diagnostico"] = True
return fin(True, "Diagnóstico local del arranque actual superado")
if not e["diagnostico"]: return fin(False, "Falta diagnóstico satisfactorio de este arranque")
if not persistencia: return fin(False, "No se confirmó la aceptación durable")
m["estado"] = "valida"
e.update(confirmada=e["ejecutando"], fase="estable", diagnostico=False,
minimo=max(e["minimo"], m["seguridad"]))
return fin(True, "Aplicación confirmada; mínimo de seguridad actualizado sin disminuir")
return fin(False, "Acción desconocida")
estado = nuevo()
escenarios = 0
def paso(nombre, accion, esperado, **cfg):
global estado, escenarios
antes = deepcopy(estado)
r = aplicar(estado, accion, **cfg)
assert r["ok"] == esperado, nombre
assert estado == antes, "El argumento no debe modificarse"
if not esperado: assert r["estado"] == antes, "Rechazo sin cambios"
estado = r["estado"]
assert estado["minimo"] >= antes["minimo"]
assert (estado["seleccion"] is not None) == (estado["fase"] == "preparada")
if estado["fase"] == "estable": assert elegible(estado, estado["ejecutando"])
if estado["fase"] == "prueba":
assert estado["slots"][estado["ejecutando"]]["estado"] == "pendiente"
if estado["fase"] == "recuperacion": assert estado["ejecutando"] is None
escenarios += 1
print(f'{nombre:30} {estado["fase"]:12} ejecuta={estado["ejecutando"]} mínimo={estado["minimo"]}')
paso("Firma rechazada", "instalar", False, firma=False)
paso("Clave ajena", "instalar", False, clave=False)
paso("Contenido alterado", "instalar", False, integridad=False)
paso("Sin autorización", "instalar", False, autorizado=False)
paso("Otra placa firmada", "instalar", False, perfil="otra_placa")
paso("Instalación no persistida", "instalar", False, persistencia=False)
paso("Preparar candidato", "instalar", True)
assert estado["ejecutando"] == "A"
paso("No aceptar antes de arrancar", "confirmar", False)
paso("Primer arranque", "reiniciar", True)
paso("No actualizar en prueba", "instalar", False)
paso("No aceptar sin diagnóstico", "confirmar", False)
paso("Diagnóstico fallido", "diagnosticar", False, salud=False)
paso("Reset sin confirmar", "reiniciar", True)
assert estado["ejecutando"] == "A" and estado["slots"]["B"]["estado"] == "invalida"
paso("Preparar otro intento", "instalar", True)
paso("Falla verificación al boot", "reiniciar", True, arranque=False)
assert estado["ejecutando"] == "A"
paso("Preparar nivel 2", "instalar", True, perfil="seguridad2")
paso("Arrancar nivel 2", "reiniciar", True)
assert estado["minimo"] == 1
paso("Diagnóstico satisfactorio", "diagnosticar", True)
paso("Aceptación no persistida", "confirmar", False, persistencia=False)
paso("Confirmar nivel 2", "confirmar", True)
assert estado["minimo"] == 2 and not elegible(estado, "A")
paso("Build mayor, seguridad menor", "instalar", False, perfil="anterior")
paso("Reset confirmado", "reiniciar", True)
assert estado["ejecutando"] == "B"
print("\nEscenario independiente: respaldo no disponible")
estado = nuevo()
paso("Preparar prueba", "instalar", True)
paso("Arrancar prueba", "reiniciar", True)
paso("Falla sin respaldo válido", "fallar", True, respaldo=False)
assert estado["fase"] == "recuperacion"
paso("No instalar desde recuperación", "instalar", False)
print("\nEscenario independiente: migración destructiva")
estado = nuevo()
paso("Preparar esquema 2", "instalar", True, perfil="migracion")
paso("Arrancar para migrar", "reiniciar", True)
paso("Datos aún incompatibles", "diagnosticar", False)
paso("Migración no persistida", "migrar", False, persistencia=False)
paso("Sobrescribir datos a 2", "migrar", True)
assert estado["datos"] == 2
paso("Falla después de migrar", "fallar", True)
assert estado["fase"] == "recuperacion" and estado["slots"]["A"]["estado"] == "valida"
print(f"\n{escenarios} escenarios superados; sin firmas ni eFuses reales.")Los 32 escenarios comprueban resultados, rechazo sin cambios, mínimo no decreciente, selección coherente y estados de ejecución. Las aserciones adicionales distinguen reversión útil, respaldo bloqueado y datos incompatibles.
11 · Dos slots y decisiones de aceptación
Laboratorio de aceptación y respaldo
Aplicá una acción por vez. El perfil queda fijado al instalar; no cambia un candidato ya preparado. Cada flag representa una verificación externa o una condición del escenario. No ingreses claves ni certificados reales.
Aplicación confirmada y candidato
Escenario listo. A está confirmada; B está vacía.
Estado de los slots
| Slot | Build | Seguridad | Esquema requerido | Estado de imagen | Operativa | Seleccionada |
|---|
Historial de decisiones
| Paso | Acción | Resultado | Fase final | Motivo |
|---|
Registro simulado
Recorrido guiado
- Desactivá firma e intentá instalar: se rechaza y A sigue estable. Restaurala, probá la imagen de otra placa y observá que una firma correcta tampoco elimina esa incompatibilidad.
- Elegí el perfil normal e instalá. B queda nueva y seleccionada; A continúa operativa. Reiniciá: B pasa a pendiente y fase prueba.
- Intentá confirmar sin diagnosticar. Después desactivá salud e intentá diagnosticar. Ambos intentos se rechazan sin confirmar la aplicación.
- Reiniciá otra vez, todavía sin confirmar. B queda inválida y se recupera A. No hay un éxito implícito por haber iniciado B una vez.
- Con salud restaurada, elegí seguridad 2, instalá y reiniciá. El mínimo todavía vale 1: la aplicación anterior sigue disponible bajo esa política.
- Diagnosticá, desactivá persistencia e intentá confirmar: sigue en prueba. Restaurala y confirmá. El mínimo pasa a 2 y A deja de ser respaldo elegible por su nivel.
- Elegí build 4 con seguridad 1 e intentá instalar. El número de build es mayor, pero se rechaza por nivel inferior al mínimo.
- Creá un escenario nuevo. Restaurá las condiciones, instalá y arrancá un candidato normal. Desactivá respaldo y declaralo fallido: no queda alternativa y se entra en recuperación.
- Creá otro escenario nuevo, restaurá respaldo y elegí el perfil que requiere esquema 2. Instalá y arrancá. El diagnóstico no pasa mientras los datos sigan en 1.
- Simulá migración y después declaralo fallido. A conserva imagen válida, pero ya no puede trabajar con el esquema 2: también se requiere recuperación. La próxima práctica consiste en diseñar una migración que conserve una salida útil.
«Nuevo escenario ficticio» conserva las opciones de los controles y crea otro registro desde cero. Recargar la página también pierde esta simulación. No representa una forma de reducir el mínimo de un chip ni de borrar el estado de seguridad de una unidad.
¿Por qué aparece «procesada» si el resultado es recuperación?
El modelo pudo aplicar la decisión de descartar el candidato, pero no encontró respaldo operativo. No presenta ese resultado como éxito de actualización: la fase y el motivo indican que se requiere intervención autorizada.
12 · Probar el camino de salida
Pruebas y diagnóstico
- Definí confianza: qué claves autorizan qué producto y cómo se protegen.
- Comprobá artefactos negativos: firma incorrecta, clave ajena, contenido alterado y hardware incompatible.
- Verificá las particiones: capacidad final y preservación de una aplicación útil.
- Definí salud y plazo: criterios locales, estados seguros y dependencia de servicios externos.
- Ensayá aceptación fallida: diagnóstico negativo, retorno de error y reset sin confirmar.
- Ensayá ausencia de respaldo: imagen inválida, mínimo de seguridad y datos incompatibles.
- Probá migraciones: cortes, versiones salteadas y conservación o restauración del formato previo.
- Probá cambios de política: claves, nivel mínimo y compatibilidad del material de recuperación.
- Registrá evidencia: build, slot, estado, motivo y resultado de recuperación, sin secretos.
| Síntoma | Qué revisar |
|---|---|
| Se rechaza una imagen firmada | Clave admitida, cobertura de firma, formato, producto y política de versión |
| Vuelve a la anterior al reiniciar | Estado pendiente, diagnóstico, confirmación y sus retornos |
| No existe reversión posible | Otra imagen válida y nivel mínimo aplicable |
| Arranca la anterior, pero no funciona | Datos migrados, configuración y dependencias que cambiaron |
| Un error tardío no revierte | La prueba inicial ya pudo estar confirmada; aplicar respuesta a fallos tardíos |
Se cortan alimentación y red en puntos definidos del proceso real, no solo al final de una descarga. Un simulador lógico no demuestra atomicidad de flash, comportamiento de eFuses ni resistencia de la cadena de arranque. Esas garantías se validan con la plataforma, su configuración y hardware.
«Si está firmado, está libre de errores»
La firma autentica el contenido bajo una política. Las pruebas y el diagnóstico evalúan funcionamiento.
«Tengo dos slots, así que siempre puedo volver»
El otro slot puede no contener una imagen admisible o sus datos pueden haber dejado de ser compatibles.
«El hash incluido en el mismo archivo reemplaza la firma»
Se necesita un valor esperado autenticado y un mecanismo de autorización apropiado. Un atacante podría cambiar archivo y hash juntos.
«Confirmo al arrancar para que no me moleste el rollback»
Eso consume la oportunidad de prueba sin obtener evidencia de salud. Se confirma después del diagnóstico definido.
«Al volver al firmware anterior vuelven los datos anteriores»
Los datos persistidos no se restauran automáticamente al cambiar de slot. La migración necesita su propio plan.
«Subir el mínimo de seguridad no afecta la recuperación»
Puede excluir imágenes que antes eran admitidas. Se comprueba el respaldo y el procedimiento de recuperación antes de cambiar la política.
13 · Práctica guiada
Predecí antes de comprobar
1. Firma de una clave desconocida
La firma es matemáticamente correcta, pero la clave que la produjo no pertenece al conjunto autorizado. ¿Se acepta la imagen?
Ver solución
No. La verificación necesita una autoridad admitida para ese propósito. La corrección matemática no incorpora automáticamente una clave a la confianza del producto.
2. Reset en prueba
A está confirmada. B arrancó pendiente y se reinicia sin confirmar. Ambas tienen seguridad 1 y datos compatibles. ¿Qué intenta el modelo?
Ver solución
Descarta B y vuelve a A. El primer arranque no equivalía a aceptación.
3. Aceptación no persistida
El diagnóstico pasó, pero falla la persistencia al confirmar. ¿Se anuncia que la nueva aplicación quedó aceptada?
Ver solución
No. El modelo conserva el estado de prueba. La implementación comprueba el retorno y aplica su recuperación, sin inventar un éxito.
4. Build mayor y nivel menor
El mínimo vale 2 y llega build 4 con nivel de seguridad 1. ¿El número de build permite instalarlo?
Ver solución
No. Build y nivel de seguridad cumplen funciones distintas. El candidato queda por debajo del mínimo.
5. Momento de elevar el mínimo
B tiene seguridad 2 y está en prueba; A tiene 1. ¿Por qué el modelo mantiene mínimo 1 hasta confirmar B?
Ver solución
Para conservar la posibilidad de recuperar A mientras se evalúa B. Al confirmar y elevar el mínimo, A deja de ser elegible por esa política.
6. Migración destructiva
B sobrescribe los únicos datos de esquema 1 a 2 y luego falla. A solo entiende 1. ¿Una firma válida de A garantiza recuperación operativa?
Ver solución
No. Puede conservar autenticidad y aun así no leer los datos. Se necesitaba compatibilidad, una copia recuperable u otra estrategia de migración.
7. Caída del servicio externo
La red ya estaba caída y el firmware nuevo no puede contactar la nube. ¿Siempre debe considerarse un defecto que exige reversión?
Ver solución
No automáticamente. El producto distingue salud local, requisitos esenciales y disponibilidad externa. Se aplica el criterio diseñado con su plazo y evidencia.
8. Fallo un mes después
La aplicación fue confirmada al instalarse y falla un mes después. ¿Debe asumirse que el rollback inicial actuará por sí solo?
Ver solución
No. La aceptación inicial ya terminó. Hace falta la respuesta a fallos tardíos: gestión autorizada, otra actualización o recuperación según el producto.
14 · Síntesis
Ideas para recordar
- Firma, compatibilidad y salud operativa aportan evidencias diferentes.
- La clave privada de publicación se protege fuera de la flota; la confianza del verificador tiene un origen definido.
- Los slots conservan imágenes y los metadatos controlan su selección y aceptación.
- El candidato arranca en prueba y requiere diagnóstico antes de confirmar.
- Un reset sin aceptación no debe convertirse en éxito implícito.
- La reversión necesita otra imagen admisible y capaz de operar con los datos existentes.
- Anti-rollback puede excluir un respaldo anterior aunque siga correctamente firmado.
- Una migración de datos puede cerrar la salida que ofrecía el firmware anterior.
- El modelo lógico no sustituye pruebas de cortes y recuperación en la plataforma real.
¿Listo para el tema 45?
Antes de avanzar, definí los criterios de aceptación de tu firmware y explicá qué aplicación y qué datos quedarán disponibles si el candidato falla. Anotá también qué evidencia reportará el equipo para distinguir actualización aceptada, reversión y recuperación pendiente.
En el próximo tema, Gestión y monitoreo de flotas, organizamos versiones, estado, registros y diagnóstico para muchos dispositivos.