Autor Tema: Bootloader encriptado para Attiny88  (Leído 18536 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Bootloader encriptado para Attiny88
« en: 16 de Septiembre de 2015, 15:27:45 »
Quiero hacer un pequeño bootloader a través de I2C encriptado con algoritmo XTEA o similar para un Attiny88

¿Alguien sabe si ya hay algún proyecto parecido?

Planeta9999 hizo uno similar para un PIC32: http://www.todopic.com.ar/foros/index.php?topic=40379

Otra duda que tengo es qué sistema de encriptación utilizar. ¿Con XTEA es suficiente?

Un saludo.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #1 en: 16 de Septiembre de 2015, 15:37:02 »
El micro con el que voy a trabajar es un Attiny88 que tiene 512 bytes de ram y 8kbytes de Flash. Ejecuta 8 millones de instrucciones por segundo (4 millones de saltos)

He leído que hay 3 algoritmos TEA:
  TEA. Parece ser que está obsoleto. XTEA lo mejora en seguridad sin añadir complejidad
  XTEA Versión mejorada del anterior
  XXTEA versión mejorada del anterior. Ocupa más ROM.

¿Es así como he comentado?

Por lo que parece el XTEA es el mejor para mi caso (relativamente seguro y ocupa poco). La velocidad no me preocupa, porque el Attiny es rápido y actualizar el firmware no es algo que se haga todos los días.

Otro del que he leído es el RC4. Parece tan sencillo como el XTEA, pero no sé cuál será mejor para un Bootloader.

Un saludo.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Bootloader encriptado para Attiny88
« Respuesta #2 en: 17 de Septiembre de 2015, 00:14:33 »
Yo tampoco puedo comparar entre uno y otro.

Pero para que quede claro, estas pidiendo un bootloader que carga un archivo encriptado. O un bootlader encriptado?

El primero buscate un ejemplo de bootloader Y cada X bytes lo pasas por el "desencriptador" o tal ves si tenes un algoritmo que pueda manejarse con un stream de datos, es decir uno detras de otro, por ahi mejor.
El segundo, vas a tener que tener el desencriptador limpio, y luego que al comienzo si se cumple una condicion ( ejemplo un pin ) proceda a desencriptar el bootloader, cargarlo en la RAM y de alli ejecutarse. Sino deberias esecribir la FLASH, y si lo vas a hacer tenes que asegurarte luego de borrar unicamnete eso, seria uan perdida de espacio bastante grande.

Si no me equivoco hay un AN de Microchip con respecto a la implementacion del XTEA.

Con respecto a ejemplos:
https://code.google.com/p/picoboot/
https://code.google.com/p/picoboot/source/browse/trunk/picobootSerial.S

Le falta todo lo demas, la encriptacion + buffer, etc. Tenes que recordar que en C tenes el que normalmente se llama c_init, que es el que inicializa las variables, el stack y varias verduras mas para que funcione.

Tmbien tenes :

http://www.avrfreaks.net/projects
Busca por bootloader

Lo primero que salio en google. Utiliza la UART, que no te costaria nada cambiarlo al I2C

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #3 en: 17 de Septiembre de 2015, 10:08:20 »
Lo que quiero es un bootloader que reciba un archivo encriptado, lo desencripte y lo escriba en la flash.

Lo de utilizar I2C es porque es el estandar serie de ese chip (no tiene UART y no quiero hacerla por soft)
La rutina I2C ya la tengo programada y funciona, pero para ahorrar espacio me gustaría compartirla con la aplicación y no tengo claro cómo hacerlo (con punteros, memoria global compartida, ...)

El programa para decodificar XTEA ya lo tengo funcionando en el PC. Me falta una buena implementación en el Atmel.

El picoboot ya lo había visto, pero es de otro tipo. Simula una UART por soft y no encripta ni comparte rutinas.

En AVRfreaks había encontrado un enlace muy interesante sobre Bootloaders:
   http://www.avrfreaks.net/forum/faq-c-writing-bootloader-faq?page=all

Resuelve muchas dudas prácticas

Ahora me falta implementarlo y no quiero inventar la rueda. Si hay otro similar al que quiero hacer, lo adapto y listo.
También me gustaría ver otros con alguna de las características que quiero, para inspirarme.

Un saludo.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #4 en: 17 de Septiembre de 2015, 10:19:36 »
Mi rutina I2C trata prácticamente todos los casos y ocupa 494 bytes. Debería reutilizarla entre bootloader y aplicación.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Bootloader encriptado para Attiny88
« Respuesta #5 en: 17 de Septiembre de 2015, 10:51:02 »
Citar
La rutina I2C ya la tengo programada y funciona, pero para ahorrar espacio me gustaría compartirla con la aplicación

¿Es decir que vaya el bootloader + aplicacion todo encriptado?
¿o queres decir que queres compartir la rutina del I2C tanto para el bootloader como para la aplicacion?

Yo decia que del picobot tomaras unicamente la parte de grabar la EEPROM + vectores de reset,etc y que solo crearas la parte de I2C el cual te comunicarias con eso. No es necesario una UART, en ves que exista una funcion que devuelve valores desde la UART lo que harias es tomar datos pero de ahora una funcion que maneja el I2C. Por eso no pense que habia demasiado cambio.

El otro tema es, en que lenguaje estas haciendo las cosas?.
Tu rutina esta en C? y queres compartirla con ambos ( bootloader + aplicacion ) entonces primero vas a tener que iniciar stack/variables/etc, lo que es igual a llamar al c_init/startup y te lo da atmel y lo pone siempre en el vector de reset.
Luego podrias hacer tu propia seccion para el bootloader, digamos al final de la memoria y hacer la funcion en C

http://www.atmel.com/webdoc/AVRLibcReferenceManual/mem_sections_1c_sections.html
http://www.atmel.com/Images/doc32158.pdf

void bootloader() __attribute__((section("name")));

void bootloader() {

  Esto llamado directamente desde el main() o si queres llamarlo desde el c_init/startup y que luego llame al main
  Debo acualizar? Sino salgo y que siga corriendo el programa.
  Sino grabo la Flash excepto la seccion del bootloader, es decir .text , .intvect, etc.
  Y produzco un reset del micro, o lo cuelgo para siempre
}

Eso en C, es lo que se me ocurre, si queres hacer mezcla ASM/C se puede complicar un poco mas, ya que podrias llamar a las funciones I2C desde el ASM pero hay que empezar a respetar las convenciones que tienen para llamarse, etc. Pero si vas a utilizar C si o si tiene que correr tu c_init/startup.
Tambien las funciones de I2C deberian incluirse dentro de la seccion del bootloader ya que no van a poder ser modificadas mientras se estan utilizando, la otra es mover estas funciones a la RAM y usarlas desde alli, pero eso va a depender del micro si es que puede correr codigo desde la RAM.

Lo feo que encuentro de esto, al volver a reescribir hasta los vectores de interrupciones, es que si por algun motivo no se llega a grabar, ejemplo se corta apenas comienza, ya no va a entrar al startup nunca mas. Lo cual puede que sea mejor tambien reubicar los vectores de resets (si es que se puede obvio) y dejar el bootloader + startup/c_init en el comienzo y evitar que este lugar sea grabado.
« Última modificación: 17 de Septiembre de 2015, 11:02:53 por KILLERJC »

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re: Bootloader encriptado para Attiny88
« Respuesta #6 en: 17 de Septiembre de 2015, 11:06:06 »
.

A cualquier bootloader estandar es muy fácil implementarle la rutina para desencriptar XTEA.

En Wikipedia tienes la rutina XTEA en C, practicamente lista para meterla en cualquier código en C, bien para PC o microcontroladores.
https://es.wikipedia.org/wiki/Extended_Tiny_Encryption_Algorithm#Implementaci.C3.B3n_en_C

Incluso te dan la rutina para encriptar, que es casi igual a la de desencriptar, solo que en la fórmula en vez de sumar, resta. De ahí lo pillé yo para mi bootloader, así que está más que probado y funciona a la perfección.

El XXTEA no lo conocía, pero también lo tienes en Wikipedia, y también te dan el código en C, para implementarlo en un momento.
https://en.wikipedia.org/wiki/XXTEA#Reference_code

Y si quieres usar RC4, de nuevo Wikipedia te da toda la información, incluido el código fuente en C para implementarlo.
https://en.wikipedia.org/wiki/RC4#RC4_variants

Lo que necesitarás, y creo que no lo has mencionado, es un encriptador XTEA, yo colgué una demo del ejecutable del mío, pero no es de código abierto, y por lo tanto la clave de encriptación no la puedes cambiar. Tampoco es muy complicado hacerse un encriptador, yo partí de un fuente en C para Visual Studio, al que añadí la rutina para abrir el archivo HEX original, la rutina de encriptación y la rutina para grabar el nuevo archivo encriptado.

Para el microcontrolador, no te compliques la vida, cualquier bootloader estandar te vale, y meterle la rutina de desencriptación XTEA se hace en unos minutos. Donde tendrás el curro realmente es en hacer el programa de encriptación, recomendable usar un entorno visual como Visual C++ o Visual Basic.
« Última modificación: 17 de Septiembre de 2015, 11:18:45 por planeta9999 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Bootloader encriptado para Attiny88
« Respuesta #7 en: 17 de Septiembre de 2015, 11:23:25 »
Podrias hacerlo en python... O buscarla por internet:

https://pypi.python.org/pypi/xtea/0.4.0
http://code.activestate.com/recipes/496737-python-xtea-encryption/

Y no necesitarias de una GUI,etc, ademas lo agregas a tu coleccion de utilidades de python :)

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #8 en: 17 de Septiembre de 2015, 12:32:27 »
Por partes:

1. El bootloader tiene una rutina de tratamiento del I2C de unos 500bytes
La aplicación también usa I2C. No tiene sentido que duplique el código. Lo mejor es utilizar la misma rutina que ya tiene el bootloader, llamándola desde la aplicación.
Así ahorro espacio.
El problema es llamar a una función del bootloader desde otro código fuente distinto. Hay que ponerse de acuerdo en dónde van a estar las variables (el buffer por ejemplo).
Hay muchas soluciones y no sé cual será la mejor. Creo que me voy a decantar por los punteros, que parece más sencillo que la memoria global fija.

2. Utilizo siempre C. Si hace falta algo de ASM, lo meto en una función C.

3. Miraré lo del  c_init/startup, que no lo conozco.

4. La recuperación ante errores es otro tema que estoy estudiando. Quiero combinarlo con una comprobación de memoria.
El bootloader se inicia primero. Comprueba la Flash. Si el checksum no es correcto, no inicia la aplicación y se queda en modo bootloader.

5. En el vector de reset quiero dejar fijo un salto al bootloader
    El vector de reset de la aplicación, se reubica al final de la flash, antes del bootloader
    Al finalizar el bootloader, salta a esta dirección reubicada.

    Ante un reset siempre se inicia el bootloader, que salta a la aplicación al cabo de un tiempo. (Como en el Arduino)
    Si se recibe en el primer segundo algún dato I2C, entonces continua en bootloader hasta que le llegue el final del archivo.

    La aplicación tendrá una orden I2C que provoque un reset software. Así tendré varias formas de entrar en el bootloader.

6. El XTEA que tengo funcionando es el de Wikipedia, pero me parecía que no estaba optimizado para micros de 8 bits.
    Lo haré yo mismo.

7. En cuanto al RC4, el problema no es implementarlo, que es muy fácil.
    Lo que quiero sabe es si es mejor opción que el XTEA.

8. La aplicación del lado PC no sé si va a existir.
    La carga del bootloader tiene que ir por I2C, de forma que lo voy a tranferir a partir de un Arduino.
    Cargas el programa en el Arduino y él se encarga de grabar el nuevo firmware en la placa.
    No hay opciones, y el IDE es el de Arduino.

Un saludo.
« Última modificación: 17 de Septiembre de 2015, 12:36:13 por Picuino »

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #9 en: 17 de Septiembre de 2015, 12:39:44 »
9. La solución Python no me gusta porque supone que el cliente tendrá Python instalado o que lo va descargar en formato portable.
En cualquier caso ocupa mucho. Preferiría utilizar LUA o una aplicación compilada (VisualBasic o similar)

En cualquier caso el Arduino tendrá que estar ahí para traducir a I2C

Otra solución es utilizar el puerto serie y una UART software por los mismos pines que el I2C. Me lo pensaré.
Pero Arduino sigue siendo necesario para convertir USB a UART. La mayoría de los usuarios Arduino no tienen un conversor USB-RS232 y quiero hacerlo fácil para ellos (que muchas veces no tienen mucho nivel)

Un saludo.
« Última modificación: 17 de Septiembre de 2015, 12:42:08 por Picuino »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Bootloader encriptado para Attiny88
« Respuesta #10 en: 17 de Septiembre de 2015, 14:00:12 »
Solo quiero corregirme una cosa en AVR-LIBC el archivo de startup/c_init o como se le quiera llamar, que es el que esta ubicado en el vector de reset se llama:

crt0.S o crt1.S

Este archivo lo que hace es como ya dije inicializar el stack, copiar los valores de una tabla desde la flash a la RAM, para inicializar las variables de la seccion .data (variables inicializadas), inicializa registros para los saltos indirectos. y creo que nada masi.

Citar
La aplicación también usa I2C. No tiene sentido que duplique el código. Lo mejor es utilizar la misma rutina que ya tiene el bootloader, llamándola desde la aplicación.
Así ahorro espacio.
El problema es llamar a una función del bootloader desde otro código fuente distinto. Hay que ponerse de acuerdo en dónde van a estar las variables (el buffer por ejemplo).
Hay muchas soluciones y no sé cual será la mejor. Creo que me voy a decantar por los punteros, que parece más sencillo que la memoria global fija.

Nuevamente si tenes funciones en C, compiladas desde C, apenas entra el ASM generado va a guardar los datos al stack y van a tratar de utilizar todas las variables inicializadas como si ahi estuvieran, si vos quitas el esa inicializacion del vector de reset entonces no hay ciencia cierta de que pueda salir de esa funcion, aunque podrias llamarlo luego desde tu bootloader, pero deberias modificar ese codigo ASM. Asi que estas un poco como obligado a hacerlo. En ves de llamar a tu bootloader desde el vector de reset, usas esta funcion, usas el main() para tu bootloader, ya que ahi salta siempre estos codigos.

Código: C
  1. #ifdef __AVR_ASM_ONLY__
  2.         XJMP    main
  3. #else   /* !__AVR_ASM_ONLY__ */
  4.         XCALL   main
  5.         XJMP    exit
  6. #endif  /* __AVR_ASM_ONLY__ */
  7. ;       .endfunc

La ubicacion esta a tu gusto, veras los pros/cons de cada uno.
El main(bootloader) ubicado al comienzo, todo lo demas apartir de la proxima pagina, I2C, todo tu programa. Sus ventajas es que esta todo juntito no hay problemas, las desventajas es que no podes reescribir los vectores de interrupcion, a no ser que crees una tabla aparte poniendole todos saltos y ubicandola en otro lugar.

La otra es ponerlo al final de la flash. Lo bueno de esto es que se podria reescribir, ya que una ves ejecutado la inicializacion ya no te importa mas esa rutina de crt0.S y podes trabajar en C tranquilo, desventajas perder algo mas de espacio.

Con respecto a la ubicacion de los I2C, creo que hay 2 opciones.
- Una es como decis, la de poner punteros a la funcion en valores de memoria fijos ( tal ves al comienzo del todo el codigo ), tomar ese valor y llamarlas.
- La otra es poner la funcion de I2C junto con el bootloader si es que entra en una pagina todo. Suponiendo que no vuelva a cambiarse (por que funciona perfectamente) y ademas todo va a depender si hay espacio para eso E imagino que vas a tener que realizar lo mismo con punteros pero ahora para  tu programa.

No entiendo por que tendrias problemas con el buffer, simplemente crealo en C, que lo acomode solo el linker y lo llamas desde ahi. Total esta en la RAM. Si queres utilizar el I2C en C entonces ya va a estar creado todo lo de las variables

Citar
4. La recuperación ante errores es otro tema que estoy estudiando. Quiero combinarlo con una comprobación de memoria.
El bootloader se inicia primero. Comprueba la Flash. Si el checksum no es correcto, no inicia la aplicación y se queda en modo bootloader.

Normalmente tenes 2 comprobaciones de memoria, una en el envio de datos, por ejemplo cada 4 bytes  , enviar 1 byte de cheksum. y la otra es cuando grabas y comprobas lo grabado.
Lo que si hay que ingeniarsela que ante un corte de corriente etc que haga que se resetee mientras grababa las primeras posiciones no afecte en nada. Esto es lo mas complicado. Ya que como minimo necesitarias de esos algunos bytes como para tener la rutina de inicializacion + vectores de interrupcion (todo por el I2C en C), sino con que grabara unicamente el vector de reset ya no habia forma de errarlo, no creo que justo falle en el primer byte .
Igual esto puede pasar casi nunca. pero mejor intentar prevenir que curar.

Citar
7. En cuanto al RC4, el problema no es implementarlo, que es muy fácil.
    Lo que quiero sabe es si es mejor opción que el XTEA.
XTEA es mas seguro. Si es que a eso vamos. No importa tanto lo eficiente, si esto se va a ejecutar solo cuando vayas a grabarlo.

Citar
. La solución Python no me gusta porque supone que el cliente tendrá Python instalado o que lo va descargar en formato portable.
En cualquier caso ocupa mucho. Preferiría utilizar LUA o una aplicación compilada (VisualBasic o similar)

No entiendo por que debe tener python instalado el cliente, vos provees con el archivo encryptado con la extension que quieras, se envia encryptado al micro y en el micro antes de grabarlo se desencripta. Y una clave que solo tengas vos y este dentro del integrado nomas.

Sino no tiene sentido.
Es vulnerable si el programa "cliente" lo desencripta y luego envia sin encriptar
Y menos que menos si se lo das desencriptado y que el programa lo encripte para que el micro lo desencripte.
« Última modificación: 17 de Septiembre de 2015, 14:05:15 por KILLERJC »

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #11 en: 17 de Septiembre de 2015, 18:53:05 »
El problema de fallo de corriente en el primer byte no le veo solución sencilla. Lo pensaré con calma.

Creo que al final será mejor poner el bootloader en las últimas posiciones.

El problema que veo para compartir memoria es que en gnu-avr no puedes decir al compilador dónde va a estar una variable en RAM. Siempre lo elige por tí el linker. No es como en el PIC.
Eso es algo que echo de menos. Se puede hacer con las opciones del linker, pero por lo poco que he visto no es nada intuitivo.
De forma que utilizar una dirección fija de RAM no parece sencillo. Lo mejor es utilizar un puntero a la dirección de RAM.

Pero la rutina de interrupciones ¡es una función sin parámetros! y estamos en las mismas. ¿Cómo le digo dónde está el buffer? No termino de entender bien cómo hacerlo con el linker.


La inicialización la puedo hacer yo en C y casi lo prefiero. Así controlo exactamente qué hace el código. Lo estudiaré.


Entonces elejiré el XTEA como método de encriptación

Lo del Python es para tener una aplicación que lea el fichero encriptado y lo mande encriptado al micro. Mi solución va a ser hacerlo mediante un programa de Arduino.

Un saludo.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #12 en: 21 de Septiembre de 2015, 16:39:36 »
Al final he optado por utilizar una UART software. Lo he codificado en C y me ha ocupado sólo 100bytes.

Luego he vuelto a revisar la rutina UART software en ensamblador del picoboot y sólo ocupa 26 bytes !!!

Para un bootloader, que es pequeño y se modifica poco, creo que no merece la pena programar en c.

Ahora a por el XTEA.

¿Alguien conoce una rutina en ensamblador para el Attiny?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Bootloader encriptado para Attiny88
« Respuesta #13 en: 21 de Septiembre de 2015, 16:53:25 »
Yo no poseo el codigo. Pero si tenes realizada la rutina en C, yo te ayudo a pasarlo a ASM. Vos tambien luego diras si lo vas a llamar desde una funcion C o no, asi lo unico que se le agregaria es lo de salvar los registros.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #14 en: 21 de Septiembre de 2015, 18:23:11 »
La rutina es sencilla en c:

Código: [Seleccionar]
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
    for (i=0; i < num_rounds; i++) {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    }
    v[0]=v0; v[1]=v1;
}

El problema está en que utiliza datos bastante grandes y sobrepasa la capacidad de los registros disponibles en c.
Habría que salvar los registros antes del ensamblador.

Por la ram no hay problema. Hay 512 bytes disponibles.