¿La implementación de AES más pequeña para microcontroladores?

38

¿Alguien puede recomendar una implementación pequeña y gratuita de AES-128 Rijndael para microcontroladores? Idealmente, para el PIC18, aunque una implementación general en C sería útil.

Compilar la implementación de axTLS para PIC18 y cifrar / descifrar un bloque requiere 6 KB de ROM y 750b de RAM.

Compilar rijndael-alg-fst.c para PIC18 y encriptar / desencriptar un bloque requiere 28KB ROM y 0.5KB RAM.

Compilar AES de 8 bits de Brian Gladman para PIC18 y cifrar / descifrar un bloque requiere 19 KB de ROM y 190 bytes de RAM.

¿Hay mejores variantes específicas de PIC optimizadas disponibles?

(requisitos de RAM actualizados para la versión axTLS)

Toby Jaffey
fuente
1
¿Es esto para el gestor de arranque?
Daniel Grillo
No, es para una aplicación de red
Toby Jaffey
Microchip tiene una implementación para dsPIC y PIC 24 que tiene un tamaño de código de 3,018 bytes, pero solo tenía cifrado, no descifrado. Sin embargo, adivinar esto no es suficiente para ti.
Kellenjb
@Kellenjb Interesante, pero estoy buscando algo pequeño para micros de 8 bits
Toby Jaffey
1
@mikeselectricstuff Sí, debe ser AES. Estoy tratando de interoperar con un sistema existente usando AES-128. Estoy interesado en cualquier implementación pequeña de AES, pero actualmente estoy apuntando a PIC18. Estoy usando el compilador HiTech Pro picc18.
Toby Jaffey

Respuestas:

19

Me pregunto cómo obtuviste 7.5kB de RAM con axTLS. Mirando el código, todo el contexto se almacena en esta estructura:

typedef struct aes_key_st 
{
    uint16_t rounds;
    uint16_t key_size;
    uint32_t ks[(AES_MAXROUNDS+1)*8];
    uint8_t iv[AES_IV_SIZE];
} AES_CTX;

El tamaño de esta estructura es 2 + 2 + 4 * 15 * 8 + 16 = 504. No veo variables globales en aes.c, las variables automáticas son todas pequeñas, por lo que el uso de la pila también es razonable. Entonces, ¿a dónde va 7.5kB? ¿Quizás intente utilizar toda la biblioteca en lugar de simplemente extraer la implementación de AES de ella?

De todos modos, esta implementación parece bastante simple, prefiero seguir este código e intentar optimizarlo. Sé que puede ser complicado, pero conocer los detalles de AES puede ayudarte al menos a estimar el uso mínimo absoluto de RAM.

Actualización: acabo de intentar compilar esta biblioteca en IA-32 Linux y escribir una prueba de cifrado CBC AES-128 simple. Obtuve los siguientes resultados (el primer número es la longitud de la sección hexadecimal):

 22 .data         00000028  0804a010  0804a010  00001010  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 23 .bss          00000294  0804a040  0804a040  00001038  2**5
                  ALLOC

Eso es solo 660 bytes de .bss (he declarado AES_CTX como una variable global). La mayor parte de .data está ocupada por IV y clave. No incluyo .text aquí, ya que obtendrá resultados totalmente diferentes en PIC (las secciones de datos deben ser casi del mismo tamaño en ambas arquitecturas).

Pintores de código
fuente
Leí mal por un factor de 10 en la versión axTLS. Tienes razón. Pero todavía estoy interesado en versiones más eficientes de AES ...
Toby Jaffey
55
¿Eficiente en términos de tamaño o velocidad? ¿Cuáles son las restricciones, en realidad? Tenga en cuenta que las bibliotecas más pequeñas probablemente serán más lentas: si observa el código fuente de las bibliotecas más grandes (en términos de sección de código), la mayor parte de la expansión se debe a matrices constantes precalculadas.
Code Painters el
1
En términos de RAM y huella ROM. La velocidad no es un problema, pero estoy buscando incluir mucha funcionalidad en un dispositivo pequeño.
Toby Jaffey
14

Sé que esta pregunta es un poco antigua, pero recientemente tuve que investigarla yo mismo, ya que estoy implementando AES128 en un PIC16 y un 8051, por lo que también tenía curiosidad sobre esta pregunta.

He usado algo como esto: http://cs.ucsb.edu/~koc/cs178/projects/JT/aes.c y mi uso de ram es de unos cientos de bytes y el tamaño binario es inferior a 3kb ROM.

Mi mejor consejo es leer en la página de Wikipedia http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation y comprender los diferentes modos, por ejemplo, cómo AES en modo OFB utiliza el modo ECB como un elemento básico. Además, el XOR (en modo OFB) lo convierte en una operación simétrica, por lo que cifrar / descifrar es la misma función que también ahorra espacio.

Cuando entendí cómo funcionaba realmente AES, pude implementarlo en C y luego probarlo con la especificación NIST ** (¡hazlo!

Pude adaptar AES128 en un 8051 junto con algún otro firmware de RF al hacer esta personalización y optimización. El uso de RAM (para todo el sistema) bajó de ~ 2.5kb a poco menos de 2kb, lo que significa que no tuvimos que actualizar a un 8051 con 4kb SRAM, pero podría seguir usando la versión más barata de 2kb SRAM.

** Los vectores de prueba se encuentran en el Apéndice F en: http://csrc.nist.gov/publications/nistpubs/800-38a/addendum-to-nist_sp800-38A.pdf

EDITAR:

Finalmente obtuve el código en Github: https://github.com/kokke/tiny-AES-c

He optimizado un poco para el tamaño. Salida de tamaño de GCC cuando se compila para ARM:

$ arm-none-eabi-gcc -O2 -c aes.c -o aes.o
$ size aes.o
   text    data     bss     dec     hex filename
   1024       0     204    1228     4cc aes.o

Por lo tanto, el uso de recursos ahora es de 1 KB de código, 204 bytes de RAM.

No recuerdo cómo construir para el PIC, pero si el AVR Atmel Mega16 de 8 bits es similar al PIC, el uso de recursos es:

$ avr-gcc -Wall -Wextra -mmcu=atmega16 -O2 -c aes.c -o aes.o
$ avr-size aes.o
   text    data     bss     dec     hex filename
   1553       0     198    1751     6d7 aes.o

Entonces, código de 1.5K y 198bytes de RAM.

Morten Jensen
fuente
Me pregunto cómo sería una implementación que hice en 2001 . No genera las cajas S; Son estáticos.
Kaz
6

Recientemente tomé la implementación axTLS y trabajé para reducirla tanto como pude. Puede generar fácilmente los S-boxes y ahorrarse unos pocos cientos de bytes.

static uint8_t aes_sbox[256];   /** AES S-box  */
static uint8_t aes_isbox[256];  /** AES iS-box */
void AES_generateSBox(void)
{
    uint32_t t[256], i;
    uint32_t x;
    for (i = 0, x = 1; i < 256; i ++)
    {
        t[i] = x;
        x ^= (x << 1) ^ ((x >> 7) * 0x11B);
    }

    aes_sbox[0] = 0x63;
    for (i = 0; i < 255; i ++)
    {
        x = t[255 - i];
        x |= x << 8;
        x ^= (x >> 4) ^ (x >> 5) ^ (x >> 6) ^ (x >> 7);
        aes_sbox[t[i]] = (x ^ 0x63) & 0xFF;
    }
    for (i = 0; i < 256;i++)
    {
         aes_isbox[aes_sbox[i]]=i;
    }
}

Puede obtener la fuente completa en: http://ccodeblog.wordpress.com/2012/05/25/aes-implementation-in-300-lines-of-code/

Andrés
fuente
Sabes tus cosas, Andrew. Votado : D
Alex
3

He estado haciendo una implementación en C, AES-128 solamente, llamada aes-min , con licencia MIT. Está dirigido a pequeños microprocesadores (por ejemplo, 8 bits) con poca RAM / ROM.

Tiene un cálculo opcional de programación de teclas sobre la marcha para reducir los requisitos de memoria (evitando la necesidad de una programación de teclas expandida completa en la RAM).

Craig McQueen
fuente
1

Puede encontrar esta implementación interesante. Es de un código abierto AVR crypto-libary.

Puede encontrar información general (obsoleta) y estadísticas sobre el tamaño y el rendimiento del código aquí .

AES:

Información AES

Solo jugué con la fuente SHA-1 de esa biblioteca, así que no puedo comentar sobre AES.

Rev1.0
fuente
0

El AES128 más pequeño que escribí para la serie PIC puede ejecutarse en 900 instrucciones y 42 bytes de RAM. Lo uso yo mismo en la serie PIC12 pero PIC10F206 también es posible :-).

No puedo revelar el código desde mi compañía, pero lo escribí en asm para la serie PIC10-12-16. El cifrado toma 444 bytes de código, incluida la tabla de búsqueda de 256 bytes, este código también incluye la función de carga de clave, que es de unos 25 bytes.

¡Le aconsejaría que revise el documento de AES y lo implemente usted mismo! La mayoría de las implementaciones son muy malas y usan mucho ram y rom.

También implementé AES128 para dsPIC y PIC24 y uso aproximadamente un 70% menos de espacio de código en comparación con la lib de microchip y mi código también es un poco más rápido. Números de implementación de dsPIC y PIC24:

"El cifrado tarda aproximadamente 2995 ciclos. 79.10uS @ 40 MIPS, 197.75uS @ 16 MIPS"

"DecKeySetup dura aproximadamente 567 ciclos. 14.20uS @ 40 MIPS, 35.43uS @ 16 MIPS"

"El descifrado tarda unos 3886 ciclos. 97.15uS @ 40 MIPS, 242.88uS @ 16 MIPS"

"El tamaño total del código es de 1050 palabras con tablas incluidas".

La belleza del núcleo PIC24 es que algunas instrucciones son de 32 bits y esto hace que la vida sea mucho más fácil para construir una pequeña implementación de AES128, mi código usa todas las instrucciones de 32 bits disponibles y está completamente en operación de 32 bits para que pueda portar el código rápidamente a PIC32 u otras CPU de 32 bits.

AES es muy sencillo de implementar, solo que la mayoría de las personas no lo intentan ni siquiera.

Mire el enlace: http://www.cs.bc.edu/~straubin/cs381-05/blockciphers/rijndael_ingles2004.swf

PaulHolland
fuente
¿Es de código abierto? ¿Puedes publicar el código?
Toby Jaffey
2
@Paul - ¡Bienvenido a Electrical Engingeering! Su respuesta es interesante y alentadora, pero no es realmente útil sin más detalles. ¡900 instrucciones probablemente podrían caber en un bloque de código! Consulte el enlace "editar" debajo de la respuesta para mejorarlo.
Kevin Vermeer
@PaulHolland buenas noticias, ¿dónde está el código?
Frank
2
@Paul: ¡obtendrías un montón de votos a favor en lugar del voto a favor que tienes actualmente si explicas cómo lo escribiste y publicaste el código! Si no puede publicar el código por razones de licencia, al menos explique cómo lo escribió y cómo Joby podría poner en paralelo su trabajo.
Kevin Vermeer