Un BLE Tag es barato hasta que tienes diez mil. En el momento en que la flota sale de fábrica, cada tag debe llevar ya una identidad única y confiable; si no, tu sistema de «seguimiento de activos» es en realidad un «spam de beacons anónimos» que cualquiera puede clonar. El aprovisionamiento masivo y el enrolamiento seguro son los pasos poco glamurosos que deciden si tus tags son activos o pasivos.
Esta es la guía del ingeniero para meter confianza por dispositivo en millones de tags: inyección de claves, almacenamiento en secure element vs SoC, flujo de fábrica, onboarding zero-touch y rotación de ciclo de vida.
Dos fases, una cadena de confianza
- Aprovisionamiento de fabricación: una vez, en la línea, donde el tag obtiene su identidad (par de claves, serial, atestación).
- Enrolamiento en campo: cuando el tag se une por primera vez al sistema del cliente, ligando la identidad de fábrica a un tenant, un sitio y una política.
Confundirlas es el error clásico. No inventas confianza en campo si la fábrica envió una clave en blanco o compartida.
Identidad por dispositivo: qué va dentro
Cada tag necesita:
- Un par de claves único (ECDSA P-256 o Ed25519) — la privada nunca sale del dispositivo.
- Una identidad pública verificable por el servidor: clave pública cruda, o certificado X.509 firmado por la raíz de flota.
- Un serial / EUI-64 ligado a esa clave, escrito en el mismo almacén seguro.
- Opcional: un secreto derivado de PUF por variación de silicio, para anti-clonado.
Un tag que solo emite un MAC aleatorio sin identidad firmada es trivialmente suplantable. La clave pública firmada es lo que hace que «este tag es el serial X» sea una afirmación en la que el servidor confía.
Secure element vs almacenamiento en SoC
| Opción | Riesgo extracción | Costo | Flexibilidad | Aprovisionamiento |
|---|---|---|---|---|
| Clave SoC en flash | Alto (lectura/JTAG) | Bajo | Alta | Sellar OTP/eFuse |
| Clave SoC en eFuse | Medio (decapsular) | Bajo | Media | Quemado único |
| Secure element discreto | Muy bajo | +$0.30–1 | Baja | Personalizar en planta |
| PUF + SoC | Bajo (sin clave en reposo) | Medio | Media | Derivar al arranque |
Para tags de activos que salen de tu control, un secure element o PUF valen lo que cuestan. Una clave en flash plano solo sirve para despliegues cerrados y físicamente seguros.
El flujo de aprovisionamiento de fábrica
La estación de inyección es donde nace la confianza. Un flujo mínimo y auditable:
1. SoC arranca en modo aprovisionamiento (JTAG abierto, debug habilitado)
2. TRNG en chip genera el par (kp_priv, kp_pub)
3. Estación escribe serial + kp_pub en OTP/eFuse o secure element
4. Estación firma (serial, kp_pub) con PLANT_KEY -> token de atestación
5. Estación sella dispositivo: bloquea debug, bloquea OTP, deshabilita re-provision
6. Dispositivo devuelve atestación ante reto -> estación la registra en auditoría HSM
Regla crítica: la clave privada se genera en el dispositivo, nunca en la estación. Si la estación guarda claves privadas, una estación robada = una flota clonada. La PLANT_KEY que firma atestaciones vive en un HSM, no en una laptop.
Confianza en la cadena de suministro
El token de atestación permite al servidor de enrolamiento probar que el tag salió de tu línea, no de un falsificador. Encadénalo:
DEVICE_KEY firmado por PLANT_KEY firmado por FLEET_ROOT
Mantén un manifiesto firmado (serial, hash de pubkey, lote, timestamp) en un log de auditoría append-only respaldado por el HSM. Si un lote se compromete, puedes limitar la revocación a ese lote en vez de toda la flota.
Enrolamiento zero-touch en campo
El tag debe enrolarse solo la primera vez que se enciende en el sitio del cliente:
tag enciende -> emite ENROLLMENT_ADV (serial, nonce, atestación)
gateway oye -> proxy (serial, atestación) a ENROLLMENT_SERVER
servidor verifica: ¿atestación válida? ¿serial sin usar? ¿no revocado?
servidor emite: liga tenant + clave de sesión por tag + política
servidor retorna -> gateway reenvía -> tag guarda liga, entra en NORMAL
Ningún técnico escanea un QR por tag. El «reto» en el advertisement evita el replay de un frame de enrolamiento capturado.
Bosquejo del protocolo de enrolamiento
def enroll(tag_adv, server):
serial, nonce, attest = parse(tag_adv)
if not verify_attest(attest, serial, PLANT_PUB): return REJECT
if serial in revoked_list: return REJECT
if serial in enrolled_set: return ALREADY
session_key = HKDF(nonce, server_seed)
policy = lookup_policy(serial) # sitio, clase de activo
binding = sign((serial, tenant, policy), FLEET_KEY)
log_enroll(serial, tenant, now())
return (session_key, binding, policy)
La clave de sesión es por tag y rotada; la clave de dispositivo a largo plazo solo prueba identidad en enrolamiento y en re-atestaciones periódicas.
Rotación de claves y ciclo de vida
La clave de identidad del tag puede ser fija, pero sus claves de sesión/cifrado deben rotar:
- Rota en cada re-enrolamiento (el tag cambia de sitio/tenant).
- Soporta revocación remota: el serial de un tag comprometido va a una CRL empujada a los gateways; luego se ignora.
- Re-atestación periódica (ej. cada 90 días) reaprueba que el dispositivo aún tiene su clave, cazando clones que reusaron una identidad pública filtrada sin la clave privada.
Rendimiento por lote
El aprovisionamiento masivo es un problema de línea. Números de una línea típica:
| Paso | Tiempo por tag | Rendimiento (1 estación) |
|---|---|---|
| Gen + escritura clave | 40 ms | ~25/s |
| Atestar + sellar | 60 ms | ~16/s |
| Commit log auditoría | 20 ms | ~50/s |
| Fin a fin | ~120 ms | ~8/s ≈ 29k/hora |
Paraleliza entre estaciones para llegar a seis cifras por turno. El cuello es casi siempre la tasa de firma del HSM, no el SoC.
Anti-clonado en campo
Aun con claves enroladas, un clon persistente puede reinyectar un frame capturado. Defensas:
- PUF challenge-response: el servidor envía reto aleatorio; solo el silicio genuino responde bien (sin clave que extraer).
- Objetivo móvil: rota la identidad anunciada o usa direcciones anónimas rotativas (ver artículo anti-tracking).
- Chequeo conductual: un clon que nunca se mueve o se mueve imposiblemente rápido es detectable en el servidor.
Errores que hunden una flota
- Clave compartida entre tags — una fuga compromete todo; revocar es imposible.
- Seriales en claro sin firma — trivialmente suplantados.
- Sin atestación — los falsificados se enrolan como reales.
- Dispositivos re-provisionables en campo — un tag hallado se reflashea y re-enrola.
- PLANT_KEY sin HSM — la clave de firma en una laptop es un pasivo.
Checklist OEM
- [ ] Par de claves único por tag, clave privada generada en dispositivo
- [ ] Almacén seguro sellado (eFuse/secure element/PUF) antes de enviar
- [ ] Atestación encadenada a raíz de flota, log de auditoría append-only
- [ ] Enrolamiento zero-touch con nonce de reto
- [ ] Rotación de clave de sesión por tag + revocación CRL
- [ ] Re-atestación periódica habilitada
- [ ] PLANT_KEY en HSM, rendimiento dimensionado al volumen
Un BLE Tag bien hecho es confiable al salir de la caja y sigue siéndolo toda su vida. Errar el aprovisionamiento es haber enviado diez mil beacons anónimos.