Un dispositivo de campo sellado cuya barra de luz se va llenando, junto a un router inalámbrico que envía una corriente de paquetes luminosos
Contenido

Actualizaciones de firmware OTA: lo básico para no perder equipos

Actualizaciones de firmware OTA: slots de imagen, manifiestos firmados, protección contra rollback y recuperación, según lo que piden IETF, NIST y ETSI.

Un apagón al 60% de la descarga de firmware debería costarte un reintento, no mandar a un técnico a campo. Las actualizaciones de firmware OTA son la forma en que un producto conectado corrige errores y vulnerabilidades después de salir al mercado, y también son el camino de código más riesgoso del dispositivo: como dice la arquitectura de actualización de firmware de la IETF, una actualización es, en el fondo, ejecución remota de código autorizada. En este artículo vemos las partes de un sistema de actualización que mantienen vivos los equipos (slots de imagen, manifiestos firmados, protección contra rollback, arranques de prueba con confirmación) y lo que piden los principales estándares e investigaciones, con un presupuesto de flash que puedes adaptar a tu propio micro.

Puntos clave

  • Una actualización tiene que sobrevivir a una interrupción. El RFC 9019 dice que los dispositivos no deben fallar ante una interrupción como un corte de energía, lo que en la práctica significa conservar una imagen funcional (dos slots o una imagen de recuperación) hasta que la nueva demuestre que sirve.
  • El dispositivo verifica una firma sobre un manifiesto antes de instalar. El manifiesto describe la imagen y trae un número de secuencia para que el equipo rechace una imagen más vieja aunque esté bien firmada.
  • Un arranque de “prueba” que regresa a la versión anterior si el firmware nuevo no se confirma, como en los modos test y permanente de MCUboot, convierte una mala versión en un reinicio en lugar de un equipo inservible.
  • El servidor de actualizaciones también es parte de la frontera de seguridad. La investigación sobre The Update Framework (Samuel et al., CCS 2010) diseñó para el caso de que se comprometa una llave de firma, con roles separados, umbrales y metadatos que caducan.
  • El ETSI EN 303 645 exige que los fabricantes de IoT de consumo publiquen un periodo de soporte definido para las actualizaciones de seguridad, así que el sistema de actualización tiene que durar por lo menos eso.

El problema: el código más riesgoso es el último que se termina

El soporte de actualizaciones muchas veces se agrega tarde, cuando la aplicación ya funciona, y se prueba en el banco con buena conexión y una fuente estable. En campo, las descargas se quedan a la mitad, la batería se acaba durante una escritura en flash, los equipos pasan meses sin conexión y regresan con tres versiones atrasadas, y alguien que logra llegar al canal de actualización intenta instalar algo que tú no compilaste.

Cada uno de esos casos tiene una respuesta conocida, y las respuestas condicionan el hardware: la flash tiene que caber más de una imagen, el bootloader necesita llaves y un verificador, y el dispositivo necesita algo de estado no volátil que registre qué está corriendo y si esa imagen ya se confirmó. Son decisiones que se toman cuando se dibuja el mapa de memoria, no después.

Lo que dicen los estándares y la investigación

La arquitectura de la IETF: manifiestos, firmas y números de secuencia

El RFC 9019, A Firmware Update Architecture for Internet of Things (Moran, Tschofenig, Brown y Meriac, 2021), describe las piezas para dispositivos con recursos limitados. Cada actualización se describe y se protege con un manifiesto, que puede viajar junto con la imagen o por separado. El dispositivo verifica una firma digital (o un MAC, en equipos muy limitados) sobre el manifiesto antes de instalar, usando anclas de confianza que se cargaron antes de cualquier actualización. La autorización puede exigir más de un firmante, por ejemplo el autor del firmware y el operador del equipo.

El manifiesto también trae un número de secuencia. El RFC es claro en que a un dispositivo al que se le presenta un manifiesto y un firmware viejos pero válidos no se le debe engañar para que los instale, porque la versión anterior puede tener una vulnerabilidad que la nueva ya corrigió. Firmar no basta para frenar los downgrades.

Sobre confiabilidad, dice que los dispositivos no deben fallar ante una interrupción como un corte de energía, y describe las formas usuales de lograrlo: conservar la imagen anterior como respaldo, guardar dos o más imágenes, o tener una imagen de recuperación capaz de repetir la actualización. También señala que el bootloader en sí casi nunca debería actualizarse, porque una actualización fallida del bootloader es la que no tiene vuelta atrás.

NIST: protección, detección y recuperación

El NIST SP 800-193, Platform Firmware Resiliency Guidelines (Regenscheid, 2018), se escribió para el firmware de plataforma de computadoras y servidores, pero su estructura aplica a cualquier dispositivo. Organiza los requisitos en tres principios: protección contra cambios no autorizados, detección de esos cambios cuando ocurren y recuperación a un estado bueno conocido. Un sistema de actualización embebido encaja en los tres: la verificación de firma protege, una revisión de integridad al arrancar detecta y una imagen de respaldo recupera.

MCUboot: slots, intercambios y confirmación

MCUboot, un bootloader seguro de código abierto para microcontroladores, es una implementación concreta de estas ideas. Cada área de imagen tiene un slot primario, desde donde el bootloader normalmente corre el firmware, y un slot secundario, donde se descarga la imagen nueva. Al arrancar, el bootloader revisa el hash SHA-256 y la firma de la imagen nueva y luego la instala intercambiándola o sobrescribiendo.

La función clave para la confiabilidad es el intercambio de prueba. En modo test, el bootloader mete la imagen nueva y la arranca, y si el firmware no se marca como confirmado antes del siguiente reinicio, el bootloader regresa la imagen anterior. Lo normal es que el firmware se confirme solo después de llegar a su servidor o pasar una autoprueba. El avance del intercambio se guarda en un “image trailer” al final del slot, así que un intercambio interrumpido por un reinicio continúa donde se quedó.

MCUboot también ofrece prevención de downgrade, ya sea comparando números de versión por software o comparando un contador de seguridad guardado en hardware confiable y no volátil. Su documentación aclara que la prevención por software solo está disponible en el modo de sobrescritura (overwrite-only), un detalle que muestra por qué estas funciones se eligen junto con el mapa de memoria.

Asegurar el lado del servidor

Las llaves de firma y los servidores de actualización también son blanco de ataques. Samuel, Mathewson, Cappos y Dingledine presentaron The Update Framework (TUF) en ACM CCS 2010, con el objetivo de que los sistemas de actualización de software sobrevivan a que se comprometa una llave de firma. Su diseño separa responsabilidades en roles (qué archivos son confiables, qué versiones son las actuales, qué metadatos están frescos), permite que los roles críticos exijan un umbral de varias llaves y pone fecha de caducidad a los metadatos para que el dispositivo detecte cuando le están dando información vieja. TUF se diseñó para repositorios de software en general; después las mismas ideas se adaptaron a vehículos en Uptane. Para un producto pequeño, las lecciones son mantener la llave raíz fuera de línea, separarla de las llaves que firman cada versión y darle al equipo una forma de notar que el canal de actualización dejó de decir la verdad.

Regulación: un periodo de soporte prometido

El ETSI EN 303 645 (V2.1.1, 2020), la base europea de seguridad para IoT de consumo, exige que los dispositivos que no son de recursos limitados tengan un mecanismo para instalar actualizaciones de forma segura, que usen criptografía de buenas prácticas para ello y que verifiquen la autenticidad e integridad de las actualizaciones que llegan por la red mediante una relación de confianza. También exige que el fabricante publique un periodo de soporte definido: el tiempo mínimo, como duración o fecha de fin, durante el que habrá actualizaciones de seguridad. Lo que prometas ahí, el sistema de actualización y sus llaves tienen que aguantarlo.

Un presupuesto de flash, paso a paso

Números ilustrativos para un dispositivo con 1 MB de flash interna:

  • Bootloader: 32 KB.
  • Slot primario: 448 KB para la aplicación.
  • Slot secundario: 448 KB para la imagen que llega (del mismo tamaño que el primario en un esquema de intercambio).
  • Espacio de intercambio, trailer y una pequeña zona de configuración: lo que sobra.

Así que la aplicación puede medir como máximo unos 448 KB, menos de la mitad de la flash. Si no alcanza, las opciones son flash externa para el slot secundario (y entonces la imagen normalmente se cifra, porque la flash externa es más fácil de leer), imágenes comprimidas o diferenciales (delta), o un diseño de un solo slot con una pequeña imagen de recuperación, que acepta que el equipo quede fuera de servicio mientras se reinstala.

El tiempo de descarga también cuenta. Con un throughput efectivo ilustrativo de 20 kB/s por un radio de corto alcance, una imagen de 400 KB tarda unos 20 segundos; a 2 kB/s por un enlace celular limitado o sub-GHz, más de tres minutos, durante los cuales la batería, la conexión y el usuario tienen que cooperar. Las descargas reanudables (llevar el registro de qué bloques ya llegaron) valen el código que cuestan.

Diseños de actualización, lado a lado

Diseño Sobrevive un corte de energía Sobrevive una mala versión Costo en flash Notas
Un slot, sobrescritura directa No No El mínimo Solo aceptable con una vía física de recuperación
Un slot más imagen de recuperación Sí (reinstala desde la recuperación) En parte (fuera de servicio hasta reinstalar) Bajo La imagen de recuperación tiene que poder descargar
Dos slots, sobrescribir el primario Sí, si la copia puede reanudarse No (la imagen anterior se pierde) Dos imágenes Sencillo; permite prevención de downgrade por software en MCUboot
Dos slots, intercambio de prueba con confirmación Sí Sí (regresa si no se confirma) Dos imágenes más espacio de intercambio Opción común en microcontroladores
Dos slots iguales, correr desde cualquiera (ejecución directa) Sí Sí, con soporte de trailer Dos imágenes La imagen debe compilarse para la dirección de cada slot

Qué hacer en la práctica

Reserva flash para dos imágenes desde el primer día

Decide el acomodo de slots cuando elijas el micro. Si la aplicación no cabe dos veces, planea flash externa o una imagen de recuperación desde ahora, no cuando la aplicación ya se comió todo el espacio.

Firma las imágenes y verifica un manifiesto en el equipo

Usa un bootloader mantenido que verifique firmas, deja la llave privada fuera de los servidores de compilación que no la necesitan e incluye un número de versión o de secuencia que el dispositivo compare contra lo que está corriendo.

Usa arranques de prueba con confirmación

Arranca la imagen nueva en modo de prueba y confírmala solo después de que el firmware llegue a su servidor o pase una autoprueba. Una versión que truena al arrancar debería regresar sola a la anterior.

Bloquea los downgrades a propósito

Decide si el equipo puede instalar alguna vez una versión anterior (por ejemplo, una versión de recuperación firmada) y haz cumplir la regla con una revisión de versión o un contador de seguridad en hardware.

Libera por etapas

Libera primero a una fracción pequeña de los equipos, revisa los reportes de confirmación y de fallas y solo entonces amplía. Conserva la capacidad de detener una liberación.

Qué no hacer

No actualices el bootloader como rutina; es el único componente sin respaldo. Y no pruebes las actualizaciones solo en el banco: corta la energía y la conexión en cada etapa de una actualización, muchas veces, antes de la primera liberación en campo.

Cómo aplicarlo

Si tienes una hora

Dibuja tu mapa de flash actual y marca dónde iría una segunda imagen. Escribe qué hace hoy tu equipo si se va la luz a la mitad de una actualización.

Si tienes un sprint

Integra un bootloader con verificación de firma e intercambios de prueba, y arma una prueba que corte la energía en puntos aleatorios durante una actualización unos cientos de veces y compruebe que el equipo siempre arranca una imagen válida.

Si quieres que dure toda la vida del producto

Documenta la jerarquía de llaves de firma y quién tiene cada una, define el periodo de soporte que vas a publicar y agrega datos de éxito, reversión y versión de las actualizaciones a la telemetría que revisas después de cada liberación.

La pregunta que debes hacerte: “Si la próxima versión truena al arrancar en todos los equipos, ¿qué pasa en los primeros cinco minutos y alguien tiene que tocar el hardware?”

Preguntas frecuentes

¿Qué es una actualización de firmware OTA?

Es una actualización que llega al dispositivo por su conexión de red (inalámbrica o cableada) en lugar de por un cable de programación. El equipo descarga una imagen nueva, la verifica y la instala, normalmente a través de un bootloader que puede regresar a la imagen anterior si algo sale mal.

¿Por qué las actualizaciones OTA necesitan dos slots de imagen?

Para que quede una imagen que funcione mientras la nueva se descarga y se prueba. Si la descarga se interrumpe o la imagen nueva falla, el equipo arranca la anterior. Los diseños de un solo slot necesitan una imagen de recuperación aparte para lograr lo mismo.

¿Qué es la protección contra rollback?

Es una revisión que impide que el dispositivo instale una versión de firmware más vieja, aunque esté bien firmada, porque las versiones anteriores pueden tener vulnerabilidades que se corrigieron después. Normalmente es un número de versión o de secuencia en el manifiesto, a veces respaldado por un contador en hardware.

¿Qué es un intercambio de prueba en MCUboot?

Es un modo en el que el bootloader instala y arranca la imagen nueva, pero regresa la anterior en el siguiente reinicio a menos que el firmware nuevo se haya marcado como confirmado. Protege contra versiones que no arrancan o que no logran conectarse a la red.

¿Los microcontroladores pequeños necesitan actualizaciones firmadas?

Sí, si las actualizaciones llegan por cualquier canal al que un atacante pueda llegar. El RFC 9019 está pensado explícitamente para dispositivos limitados y permite un MAC en lugar de una firma de llave pública en los más limitados. El ETSI EN 303 645 exige revisar la autenticidad e integridad de las actualizaciones que llegan por red en dispositivos IoT de consumo.

Lecturas relacionadas: RTOS vs bare metal, cómo medir el consumo de un microcontrolador y de tarjeta de desarrollo a producto.

Fuentes

  1. Moran, B., Tschofenig, H., Brown, D., & Meriac, M. (2021). A Firmware Update Architecture for Internet of Things. IETF RFC 9019. https://www.rfc-editor.org/rfc/rfc9019.html
  2. Regenscheid, A. (2018). Platform Firmware Resiliency Guidelines. NIST Special Publication 800-193. https://csrc.nist.gov/pubs/sp/800/193/final
  3. Samuel, J., Mathewson, N., Cappos, J., & Dingledine, R. (2010). “Survivable Key Compromise in Software Update Systems.” Proceedings of the 17th ACM Conference on Computer and Communications Security (CCS ’10), 61–72. https://doi.org/10.1145/1866307.1866315
  4. ETSI (2020). Cyber Security for Consumer Internet of Things: Baseline Requirements. ETSI EN 303 645 V2.1.1. https://www.etsi.org/deliver/etsi_en/303600_303699/303645/02.01.01_60/en_303645v020101p.pdf
  5. Proyecto MCUboot. “MCUboot Design.” https://docs.mcuboot.com/design.html
Escrito porAlphaCrew Studio

Creamos contenido técnico y animación, desarrollamos apps y plataformas a la medida y configuramos flujos de trabajo con IA para equipos de ingeniería y tecnología.