Una implementación SSL/TLS libre, [mbedtls](https://tls.mbed.org/) es una biblioteca que reúne una suite de herramientas para cifrado. Está hecha de tal forma que se puede portar fácilmente a dispositivos embebidos como un barato enrutador con GNU/Linux.

## Un poco sobre TLS ##

*Transport Security Layer* ([TLS](https://es.wikipedia.org/wiki/Transport_Layer_Security)) es un conjunto de protocolos que no solamente permiten cifrar comunicaciones, también permiten autenticarlas, veamos un poco de la necesidad de autenticación además del cifrado.

![de A a B](/static/imgs/posts/A_a_B1.jpeg)

En el caso 1 de arriba se ve como **A** envía a **B** un mensaje "Hola", pero hay un **espía** que está atento a lo que A y B se envían y el espía tambíen recibe "Hola".

En el caso 2 **A** toma una medida de seguridad y cifra el mismo mensaje "Hola" con algún algoritmo de cifrado y el resultado es "-, ]85*" y suponiendo que B conoce el algoritmo que ha usado A, B podrá descifrarlo y obtener "Hola".

Pero "-, ]85*" es el resultado de usar un algortmo "débil" dada su simplicidad ya que el espia con algo de conocimiento en cifrado puede con algunos cientos o miles de intentos podría descubrir el algoritmo simple que A usó para cifrar "Hola". En el siguiente caso A y B deciden usar un mejor método de cifrado:

![de A a B](/static/imgs/posts/A_a_B2.jpeg)

Ahora A ha cifrado "Hola" usando una **clave en común** que comparte con B. El mensaje resultante es:

    jA0EAwMCj9bE0UxtMdtgyR4rOyDRi1IA4fc7cP/VeSNgO1aVDqsV4H5amv7ZFjI=
	=z1GM

B usa la clave y el algoritmo que ha usado A para descifrar este mensaje como "Hola", suponiendo que el **espia** conce el algoritmo que A, B han usado, aún necesita saber la clave que han usado o al espia le será prácticamente imposible descifrar el mensaje correctamente.

Este cifrado es fuerte en tanto el espia no conozca la clave en común, pero aquí estamos suponiendo que A y B ambos ya cuentan con la clave en común. Pero este no siempre es el caso.

Por ejemplo imaginemos que A y B nunca antes se han comunicado y necesitan comunicarse de manera segura desde la primera vez. Para ello, necesitan **definir el algoritmo que usarán** e **intercambiar una clave en común** antes de comenzar a comunicarse de manera segura.

Allí es donde TLS entra en juego, agrega una capa de seguridad permitiendo a cualquier A o B a usar [criptografía asimétrica](https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica) y protocolos para intercambiar estas estas claves de manera segura.

### Criptografía asimétrica ###

De manera muy resumida con la criptografía asimétrica cualquier A, B necesitan un par de claves; una `clave privada` y una `pública`, estas dos claves están matemáticamente relacionadas y se consigue:

* Cuando se cifra con la llave privada, sólo se puede descifrar con la clave pública.
* Cuando se cifra con la clave pública, sólo se puede descifrar con la clave privada.

La clave pública está pensada para que A la comprata con cualquier otro B, C, etc. y así estos últimos puedan descifrar los mensajes que A cifre usando su llave privada. De igual manera si B usa la clave pública de A para enviarle un mensaje a A, sólo A podrá descifrar este mensaje por que se supone que A y solamente A posee su clave privada. La clave privada no se comparte con nadie.

En tanto A y B intercambien claves públicas y no revelen sus claves privadas, podrán comunicarse de manera segura. Un ejemplo de programa que permite usar este tipo de cifrado es [GNUpg](https://gnupg.org/).

### Necesidad de autenticación ###

Suponiendo que el espia no puede acceder a las claves de A o B, aún puede engañar a B fingiendo que es A:

![de A a B](/static/imgs/posts/espia_a_B1.jpeg)

En este caso el espia le dice a B que es A y le pasa una clave pública, B no tiene forma de comprobar que en realidad un espia esta intentando hacerse pasar por A y aceptará la clave que se le pase, además confiará en esta clave para comunicarse con A.

Para evitar esto se usan certificados [X.509](https://es.wikipedia.org/wiki/X.509), donde se agrega una medida de seguridad para evitar que un espia suplante a algún A. Se usan certificados firmados por autoridades certificadoras de confianza que aseguran a que A es quien dice ser. De este modo B primero confía en una autoridad certificadora **CA**. Cuando alguien le dice a B: "yo soy A, toma mi clave pública". B no confiará ciegamente en esto, primero le pedirá a CA que compruebe que la clave que se le ha pasado a B, realmente le pertenece a A.

Si CA lo comprueba, B confiará plenamente en esa clave pública y a partir de ese momento la asociará a A. Entonces el espia no podrá suplantar de nuevo a A, precisamente TLS implementa avanzados protocolos para asegurar que esto funcione correctamente.

----

Por eso todas las páginas web actualizadas y que cifran su contenido, usan TLS y se identifican con `https`, así los navegadores web y la página web intercambian contenido con un cifrado fuerte, y con las claves autenticadas de manera segura. Por defecto los nevegadores web, confían en un número de [autoridades certificadoras](https://es.wikipedia.org/wiki/Categor%C3%ADa:Autoridades_de_certificaci%C3%B3n) en internet.

## Jugando con mbedtls ##

A diferencia de [openssl](https://www.openssl.org/) que es una implementación muy conocida de TLS, mbedtls se centra en brindar una manera más sencilla de usar TLS o su conjunto de herramientas de cifrado. Además mbedtls se puede fácilmente usar en dispositivos embebidos con capacidades computacionales reducidas, para lo que sigue de este post mostraré una forma de construir mbedtls para que funcione en un enrutador TL-WDR3600 (aunque podría hacerse funcionar en un más barato como el tl-mr3020), desde una distribución GNU/Linux.

Estamos asumiendo que el enrutador tiene instalado firmware libre como lede, openwrt o librecmc.

### Construyendo mbedtls ###

Una vez descargamos el código fuente desde [https://tls.mbed.org/download](https://tls.mbed.org/download), abrimos el archivo `README.md`, veremos que este requiere de herramienetas de construcción como `make` o `cmake`. Para nuestro caso usaremos solamente make, entonces instalaremos los paquetes; `gcc`, `build-essential`, `make`. En nuestra distribución preferida GNU/Linux.

Luego vamos al directorio donde esta mbedtls y ejecutamos:

    make

Deberíamos estar atentos al procedimiento y si este termina satisfactoriamente, deberíamos poder probar por ejemplo cifrando y descifrando con `rsa`. Se ha creado una una carpeta `programs/pkey/` y allí unos ejecutables que son programas de prueba:

    cd programs/pkey
	./rsa_encrypt "Hola"

Cifrará el mensaje "Hola" con el par de claves de prueba que se crearón al hacer make; `rsa_priv.txt` y `rsa_pub.txt` y lo guarda en `result-enc.txt`, para descifrarlo se usa.

    ./rsa_decrypt

Y si vemos "Hola", significa que se ha descifrado correctamente.

### Compilación cruzada de mbedtls ###

Vamos a utilizar el SDK *Software Development Kit* de lede o librecmc para construir programas para enrutadores como el TL-WDR3600, ([revisa este post para ver como construir el SDK ](construir-firmware-para-enrutadores-con-buildroot)).

Una vez tengamos el SDK, al llamar a `make` tenemos que usar el compilador gcc para la arquitectura mips_74kc que es la arquitectura del TL-WDR3600,  en lugar del `gcc` instalado en el sistema desde el cual compilaremos.

Para simplificar la compilación cruzada, puedes utilizar este script que llamaremos `set-up.sh`. Antes de ver el script deberíamos hacer un enlace simbólico del SDK que usaremos en la misma ruta donde descomprimimos mbedtls, lo podemos hacer con:

    ln --symbolic /ruta/absoluta/hacia/el/sdk/ SDK

Por ejemplo:

    ln --symbolic /home/alguien/lede-sdk-ar71xx-generic_gcc-5.4.0_musl.Linux-i686 SDK

A continuación el script `set-up.sh`.

    :::bash
    #!/bin/bash
	
    # Para compilar:
    # 
    # ./set-up.sh build
    # ./set-up.sh clean
    
    # para copiarlo directamente al enrutador con <IP> dada (lo copia en /tmp/)
    #
    # ./set-up.sh export <IP>
        
    OP1=$1
    OP2=$2
    
    ayuda()
    {
        echo "Uso:"
        echo "Construye usando un cross compiler mips-openwrt-linux-musl-gcc:"
        echo "  ./set-up.sh build"
        echo "Equivalente a 'make clean':"
        echo "  ./set-up.sh clean"
        echo "Construye y copia al enrutador con IP (usa root@IP y copia en /tmp/):"
        echo "  ./set-up.sh export IP"
        echo "Ejemplo:"
        echo "  ./set-up.sh export 192.168.1.1"
        echo ""
        echo "NOTA Antes de ejecutar:"
        echo "  La ruta hacia el SDK de LEDE debe estar en este mismo directorio"
        echo "  puede ser con un enlace simbolico con el nombre 'SDK'"
        echo "    ln --symbolic /ruta/absoluta/hacia/el/sdk/ SDK"
    }
    
    #### 
    # setup inicial
    setup()
    {
        # agregando al path
        if ! echo $PATH | grep "mips-openwrt-linux-gcc-5.4.0/bin" 
        then
    	  RUTA_SDK=$(readlink SDK)
      	  PATH=$PATH:"$RUTA_SDK"staging_dir/toolchain-mips_24kc_gcc-5.4.0_musl/bin/
    	  export PATH
        fi
    
        # agregando staging dir
        if ! echo $STAGING_DIR | grep "lede-sdk-ar71xx-generic_gcc-5.4.0_musl.Linux-i686/staging_dir"
        then
    	  RUTA_SDK=$(readlink SDK)
    	  STAGING_DIR="$RUTA_SDK"staging_dir/toolchain-mips_24kc_gcc-5.4.0_musl/bin/
    	  export STAGING_DIR
        fi
        echo
        echo "PATH:$PATH"
        echo "STAGING_DIR:$STAGING_DIR"
    }
    ####
    
    build()
    {
        echo "Construyendo..."
        setup
        echo
        echo "CROSS COMPILER:"
        mips-openwrt-linux-musl-gcc --version
    
        # para construir mbedtls (ver README.md)
        #make CC=mips-openwrt-linux-musl-gcc LD=mips-openwrt-linux-ld
    
        # construir usando archivo de configuracion personalizado
        echo ":-:-:"
        echo "Construyendo usando archivo de configuracion distinto al por defecto"
        echo "config-mini-tls1_1.h"
        make CC=mips-openwrt-linux-musl-gcc \
		     LD=mips-openwrt-linux-ld \
			 CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE='<config-mini-tls1_1.h>'" \
             SHARED=TRUE 
    
        echo "Hecho"
    }
    
    clean()
    {
        echo "Limpiando..."
        setup
        make clean
    }
    
    exportar()
    {
        "Exportando..."
        build
        scp -r programs/pkey root@$OP2:/tmp/
    }
    
    ####
    # opciones
    if [ -z "$OP1" ]
    then
        ayuda
        exit 2
    fi
    
    if [ $OP1 == "build" ]
    then
       build
       exit 0
    fi
    
    if [ $OP1 == "clean" ]
    then
        clean
        exit 0
    fi
    
    if [ $OP1 == "export" ]
    then
        R=$(echo $OP2 | grep "[a-z,A-Z]")
        if [ -z $OP2 ] || [ $R != "" ]
        then
    	ayuda
    	exit 2
        else
    	exportar
    	exit 0
        fi
    fi
    
    ayuda
    exit 2

Para que sea más cómodo manejarlo le daremos permisos de ejecución con `chmod +x set-up.sh`

El script se encarga de primero agregar al `PATH` el compilador del SDK de lede y lo exporta. Al hacer `./set-up.sh build` se llamará al Makefile de mbedtls pero pasándole tres opciones extra para que realice la compilación cruzada correctamente:

    :::bash
    make CC=mips-openwrt-linux-musl-gcc LD=mips-openwrt-linux-ld CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE='<config-mini-tls1_1.h>'" SHARED=TRUE 

Aquí, `CC=mips-openwrt-linux-musl-gcc` indica a make que use el compilador `mips-openwrt-linux-musl-gcc` en lugar de `gcc` instalado en el S.O. De igual forma con el enlazador al modificar `LD`.

Como se indica en la documentación (ver README en configs/README.txt de mbedtls) usaremos una configuración mínima para compilar mbedtls sin por ejemplo el módulo de entropía, y se usará el archivo de configuración `config-mini-tls1_1.h`, esto se logra agregando `CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE='<config-mini-tls1_1.h>'"` al llamar a make. Finalmente `SHARED=TRUE` hace que se construyan tambíen bibliotecas compartidas (ver más adelante)

Así es como el script nos permite hacer el *cross compiling* (compilación cruzada) y una vez termina podemos probar si esto ha funcionado copiando la carpeta `programs/pkey/` en el enrutador manualmente o mediante el script y su opción "export".

Para poder probarlo, deberíamos tener instalado en el enrutador la biblioteca mbedtls, en lede se hace con:

    opkg install libmbedtls

**Si no logras instalar vía opkg**, el siguiente procedimiento podría funcionar (no lo he probado):

1. De la carpeta `library/` en el directorio donde construimos mbedtls, copiar al directorio  `/usr/lib/` del enrutador los archivos;  `libmbedcrypto.so`, `libmbedtls.so`, `libmbedx509.so`. Estos son las bibliotecas compartidas que make ha construido al definir `SHARED=TRUE` en el script.
2. Crear enlaces simbólicos en el enrutador, para que el programa de cifrado sepa que la biblioteca mbedtls esta instalada:

         cd /usr/lib/
		 ln -s $PWD/libmbedcrypto.so libmbedcrypto.so.0
		 ln -s $PWD/libmbedtls.so libmbedtls.so.10
		 ln -s $PWD/libmbedx509.so libmbedx509.so.0

2. Copiar la carpeta `programs/pkey` que se construyerón con los programas de prueba, a `/tmp/` del enrutador.

Luego en el enrutador en el directorio `/tmp/programs/pkey`, deberíamos poder ejecutar los programas para cifrar y descifrar con rsa como probamos antes, si todo funciona bien ya podemos jugar y usar la bilioteca mbedtls para hacer/modificar programas y que se puedan ejecutar en nuestros enrutadores :)

#### Modificando ####

Como mbedtls es software libre, podemos modificar el código en cualquier momento y probar los resultados de las modificaciones que hagamos, es cuestión de estudiar el código y aprender a dominarlo para hacer cosas divertidas.

Espero esta guía te haya servido, [ponte en contacto](/contacto) para consultas o correcciones.











