DÍA 163 DE 365

Fase 3: Comunicaciones y Redes Industriales

📖 Teoría a Estudiar

El Operador Matemático Perfecto: XOR

En el mundo de los microcontroladores, la encriptación pesada como AES-256 es fantástica, pero consume demasiada memoria Flash, RAM y ciclos de reloj. Cuando necesitas ofuscar datos en tiempo real (mientras despachas gas a 84MHz), necesitas algo brutalmente rápido. Aquí entra la compuerta lógica XOR (OR Exclusivo).

La magia de XOR radica en su tabla de verdad y su propiedad de reversibilidad matemática. La regla de XOR es simple: "Si los bits son iguales, el resultado es 0. Si son diferentes, el resultado es 1".

La Propiedad Criptográfica de la Reversibilidad

La característica que hace al XOR el rey de la encriptación simétrica rápida es la siguiente ecuación:

(Dato Original ⊕ Llave Secreta) = Dato Encriptado

Y para recuperarlo, aplicas exactamente la misma operación:

(Dato Encriptado ⊕ Llave Secreta) = Dato Original

No necesitas una función para encriptar y otra compleja para desencriptar. La misma función de 3 líneas de código hace ambas cosas "In-Place" (sobre el mismo arreglo de memoria), sin desperdiciar un solo byte extra de RAM.

ARQUITECTURA DE CIFRADO SIMÉTRICO: OPERADOR XOR (⊕) STM32 (TX) - Encriptando A = 0x4D 0100 1101 ⊕ K = 0xA5 1010 0101 C = 0xE8 1110 1000 Bus RS485 El hacker solo ve 0xE8 🕵️ Sniffer SCADA (RX) - Desencriptando C = 0xE8 1110 1000 ⊕ K = 0xA5 1010 0101 A = 0x4D 0100 1101

⚙️ Ejercicios Prácticos

Ejercicio 1: Interceptaremos el búfer de transmisión justo antes de que el controlador de DMA del RS485 envíe el paquete Modbus, y aplicaremos una máscara XOR con una Llave Rotativa. Un solo byte de llave es débil (un atacante lo adivinaría de inmediato). Usaremos un arreglo (array) como llave secreta y lo aplicaremos cíclicamente usando el operador módulo (%) para esconder por completo los patrones repetitivos de nuestro protocolo.


/**
 * @file xor_cipher.c
 * @brief Encriptador/Desencriptador Simétrico XOR para Tramas UART/RS485
 */

#include "stm32f401xe.h"
#include <stdint.h>

// =========================================================================
// LLAVE SECRETA SIMÉTRICA (Debe coincidir en el STM32 y en el Servidor SCADA)
// En un sistema real avanzado, esta llave puede generarse dinámicamente
// usando el número de serie único del STM32 (UID Register).
// =========================================================================
static const uint8_t LLAVE_SECRETA[] = { 0xA5, 0x3C, 0x81, 0x18, 0xFE, 0x42 };
static const uint8_t TAM_LLAVE = sizeof(LLAVE_SECRETA);

/**
 * @brief Aplica el cifrado o descifrado XOR a un búfer de datos.
 *        La función opera "In-Place", sobrescribiendo el búfer original
 *        para no desperdiciar memoria RAM creando arreglos paralelos.
 * 
 * @param buffer Puntero al arreglo de bytes que contiene el paquete a procesar.
 * @param longitud Cantidad de bytes en el paquete.
 */
void Aplicar_Cifrado_XOR(uint8_t *buffer, uint16_t longitud) {
    
    // Si la longitud es 0 o la llave no existe, abortamos por seguridad
    if (longitud == 0 || TAM_LLAVE == 0) return;
    
    for (uint16_t i = 0; i < longitud; i++) {
        // El operador ^ en C es el XOR bit a bit (Bitwise XOR).
        // Usamos (i % TAM_LLAVE) para iterar cíclicamente sobre la llave.
        // Ej: Si el paquete tiene 10 bytes y la llave 6, 
        // para el byte 7 volverá a usar el índice 0 de la llave.
        
        buffer[i] ^= LLAVE_SECRETA[i % TAM_LLAVE];
    }
}

// =========================================================================
// INTEGRACIÓN EN EL PIPELINE DE TRANSMISIÓN/RECEPCIÓN (Modbus)
// =========================================================================

// Dependencias simuladas
extern void DMA_Iniciar_Transmision_RS485(uint8_t *datos, uint16_t len); // Día 138
extern bool Modbus_Validar_CRC(uint8_t* paquete, uint16_t len);          // Día 149

/**
 * @brief Envía un paquete Modbus encriptado al Servidor
 */
void Transmitir_Paquete_Seguro(uint8_t *paquete_modbus, uint16_t longitud) {
    
    // 1. Opcional: El CRC debe calcularse ANTES de encriptar
    // (Para que el servidor lo verifique después de desencriptar).
    // Anexar_CRC16_Al_Final(paquete_modbus, &longitud);
    
    // 2. OFUSCACIÓN CRIPTOGRÁFICA
    // Destruimos la legibilidad del paquete en la RAM.
    Aplicar_Cifrado_XOR(paquete_modbus, longitud);
    
    // 3. ENVÍO FÍSICO AL HARDWARE
    // Los datos que viajan por el cable RS485 son irreconocibles.
    DMA_Iniciar_Transmision_RS485(paquete_modbus, longitud);
}

/**
 * @brief Procesa un paquete crudo recién llegado de la red
 */
void Recibir_Paquete_Seguro(uint8_t *paquete_entrante, uint16_t longitud) {
    
    // 1. DESENCRIPTADO IN-PLACE
    // Usamos EXACTAMENTE la misma función. El XOR de la basura 
    // revelará los datos legibles originales de vuelta a la RAM.
    Aplicar_Cifrado_XOR(paquete_entrante, longitud);
    
    // 2. VALIDACIÓN DE INTEGRIDAD Y AUTENTICIDAD
    // Si un atacante inyecta ruido o una trama cifrada con la llave incorrecta,
    // al desencriptarse generará basura. Esa basura jamás pasará la prueba
    // estricta del polinomio matemático del CRC-16.
    if (Modbus_Validar_CRC(paquete_entrante, longitud)) {
        
        // ¡El mensaje es auténtico, íntegro y proveniente de una fuente autorizada!
        // procesar_comandos_modbus(paquete_entrante);
        
    } else {
        // Intento de hackeo o ruido eléctrico severo. Descartar paquete en silencio.
    }
}

int main(void) {
    
    // ... Súper Bucle normal ...
    
    return 0;
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Seguridad Perimetral y Mitigación de Ataques (MitM).

En el Día 139 implementamos el Protocolo Modbus RTU. Un hacker que intercepte esos cables verá comandos evidentes como `01 06 00 00 04 1A` (Escribir Precio a $10.50). Con un equipo básico, podría inyectar su propio comando `01 06 00 00 00 01` ordenando al Despachador bajar el precio a 1 centavo, llenar su camión de gas, y largarse.

Al implementar el **Cifrado de Flujo XOR** justo antes del envío por el chip MAX485, el comando `01 06` se convierte en basura indescifrable como `A4 3A`. Como estamos usando una llave rotativa en lugar de un solo byte estático, dos comandos idénticos enviados consecutivamente se verán diferentes en la red. Si el atacante intenta inyectar sus propios comandos `A4 3A`, cuando tu STM32 aplique la llave para "desencriptarlo", generará datos corruptos que el motor de validación **CRC-16 (Día 149)** destruirá matemáticamente de inmediato, evadiendo el ataque por completo sin sobrecargar el procesador como lo harían las librerías mbedTLS o AES.

📝 Resumen del Día